<commit_before>#include "plant_generator.h"

#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <numeric>
#include <random>
#include <type_traits>

#include <asdf_multiplat/main/asdf_defs.h>

#include "from_json.h"

namespace plantgen
{
    //std::vector<std::string> roll_multi_value(multi_value_t const& m);

    std::mt19937 mt_rand( std::chrono::high_resolution_clock::now().time_since_epoch().count() );

    int random_int(uint32_t min, uint32_t max)
    {
        std::uniform_int_distribution<int> dis(min,max);
        return dis(mt_rand);
    }

    int random_int(uint32_t max)
    {
        return random_int(0, max);
    }

    template <typename L>
    uint32_t total_weight(L const& list)
    {
        uint32_t total = 0;

        for(auto const& v : list)
            total += v.weight;

        return total;
    }

    std::vector<std::string> roll_multi_value(multi_value_t const& m)
    {
        if(m.num_to_pick >= m.values.size())
            return m.values;

        std::vector<size_t> inds(m.values.size());
        std::iota(inds.begin(), inds.end(), size_t(0)); //0, 1, 2, 3, ..., size-1
        std::shuffle(inds.begin(), inds.end(), std::mt19937{std::random_device{}()});

        std::vector<std::string> output;
        output.reserve(m.num_to_pick);

        for(size_t i = 0; i < m.num_to_pick; ++i)
            output.push_back(m.values[inds[i]]);

        return output;
    }

    std::vector<std::string> roll_range_value(range_value_t const& r)
    {
        std::vector<std::string> output;
        output.reserve(r.size());

        uint32_t counter = 0;
        for(size_t i = 0; i < r.size() - 1; ++i)
        {
            int roll = 0;

            if(counter < 100)
                roll = random_int(100 - counter);

            counter += roll;
            output.push_back(std::to_string(roll) + "% " + r[i]);
        }

        //push remaining
        output.push_back(std::to_string(100 - counter) + "% " + r.back());

        return output;
    }

    /// Runtime version (compile-time visitor pattern doesn't compile in msvc)
    std::vector<std::string> roll_value(weighted_value_t const& variant_val)
    {
        std::vector<std::string> output;

        if(auto* s = std::get_if<std::string>(&variant_val))
        {
            output.push_back(*s);
        }
        else if(auto* r = std::get_if<range_value_t>(&variant_val))
        {
            auto rolled_range = roll_range_value(*r);
            output.insert(output.end(), rolled_range.begin(), rolled_range.end());
        }
        else if(auto* m = std::get_if<multi_value_t>(&variant_val))
        {
            auto rolled_multi = roll_multi_value(*m);
            output.insert(output.end(), rolled_multi.begin(), rolled_multi.end());
        }
        else
        {
            EXPLODE("unexpected variant sub-type");
        }

        return output;
    }

    generated_node_t roll_values(value_list_t const& values, std::vector<pregen_node_t> const& value_nodes)
    {
        if(values.empty() && value_nodes.empty())
            return generated_node_t();

        uint32_t total = total_weight(values) + total_weight(value_nodes);

        int roll = random_int(total);

        for(size_t i = 0; i < values.size(); ++i)
        {
            if(roll <= values[i].weight)
            {
                generated_node_t node;
                node.generated_values = std::move(roll_value(values[i]));
                return node;
            }

            roll -= values[i].weight;
        }

        //if no value from the value list has been hit yet, continue onward into value_nodes
        for(size_t i = 0; i < value_nodes.size(); ++i)
        {
            if(roll <= value_nodes[i].weight)
            {
                generated_node_t node(value_nodes[i].name);
                node.add_child(generate_node(value_nodes[i]));
                return node;
            }

            roll -= value_nodes[i].weight;
        }

        EXPLODE("Random roll was too large, ran out of values and value_nodes");
        return generated_node_t("ERROR");
    }

    generated_node_t roll_values(pregen_node_t const& node)
    {
        return roll_values(node.values, node.value_nodes);
    }

    generated_node_t generate_node(pregen_node_t const& pre_node)
    {
        generated_node_t node;
        node.name = pre_node.name;

        for(auto const& child : pre_node.children)
        {
            node.add_child(generate_node(child));
        }

        generated_node_t rolled = roll_values(pre_node);
        node.children.insert(node.children.end(), rolled.children.begin(), rolled.children.end());
        node.generated_values = std::move(rolled.generated_values);

        return node;
    }

    generated_node_t generate_node_from_file(stdfs::path const& filepath)
    {
        using namespace std;

        auto ext = filepath.extension();
        if(ext == ".json")
        {
            return generate_node_from_json(filepath);
        }
        else if(ext == ".yaml" || ext == ".yml")
        {
            cout << "TODO: yaml support";
            return generated_node_t();
        }

        if(stdfs::is_directory(filepath))
            cout << filepath.string() << " is a directory, not a file";
        else
            cout << "Filetype " << ext << " not recognized";

        return generated_node_t();
    }

    constexpr size_t indent_amt = 4;
    // constexpr char indent_char = ' ';
    // constexpr char indent_tree_marker = ':';
    constexpr char const* indent_cstr = ":   ";

    std::string indenation_string(size_t indent_level)
    {
        if(indent_level == 0)
            return "";

        // std::string indent_str(indent_level * indent_amt, indent_char);
        // indent_str[indent_str.size()-indent_amt] = indent_tree_marker;

        std::string indent_str;
        for(size_t i = 1; i < indent_level; ++i)
            indent_str.insert(indent_str.end(), indent_cstr, indent_cstr + 4);

        return indent_str;
    }

    void print_node(pregen_node_t const& node, size_t level)
    {
        using namespace std;

        auto indent = indenation_string(level);

        cout << indent << node.name << "\n";

        for(auto const& child : node.children)
            print_node(child, level + 1);

        indent.append(indenation_string(1));

        for(auto const& value : node.values)
            cout << indent << value << "\n";

        for(auto const& vnode : node.value_nodes)
            print_node(vnode, level + 1);

        for(auto const& user_val : node.user_data)
            cout << indent << user_val << "\n";
    }

    void print_node(generated_node_t const& node, size_t level)
    {
        using namespace std;

        auto indent = indenation_string(level);

        cout << indent << node.name << "\n";

        for(auto const& child : node.children)
            print_node(child, level + 1);

        indent.append(indenation_string(1));

        for(auto const& value : node.generated_values)
        {
            cout << indent << value << "\n";
        }
    }
}<commit_msg>many things<commit_after>#include "plant_generator.h"

#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <numeric>
#include <random>
#include <type_traits>

#include <asdf_multiplat/main/asdf_defs.h>

#include "from_json.h"

namespace plantgen
{
    //std::vector<std::string> roll_multi_value(multi_value_t const& m);

    std::mt19937 mt_rand( std::chrono::high_resolution_clock::now().time_since_epoch().count() );

    int random_int(uint32_t min, uint32_t max)
    {
        std::uniform_int_distribution<int> dis(min,max);
        return dis(mt_rand);
    }

    int random_int(uint32_t max)
    {
        return random_int(0, max);
    }

    template <typename L>
    uint32_t total_weight(L const& list)
    {
        uint32_t total = 0;

        for(auto const& v : list)
            total += v.weight;

        return total;
    }

    std::vector<std::string> roll_multi_value(multi_value_t const& m)
    {
        if(m.num_to_pick >= m.values.size())
            return m.values;

        std::vector<size_t> inds(m.values.size());
        std::iota(inds.begin(), inds.end(), size_t(0)); //0, 1, 2, 3, ..., size-1
        std::shuffle(inds.begin(), inds.end(), std::mt19937{std::random_device{}()});

        std::vector<std::string> output;
        output.reserve(m.num_to_pick);

        for(size_t i = 0; i < m.num_to_pick; ++i)
            output.push_back(m.values[inds[i]]);

        return output;
    }

    std::vector<std::string> roll_range_value(range_value_t const& r)
    {
        std::vector<std::string> output;
        output.reserve(r.size());

        uint32_t counter = 0;
        for(size_t i = 0; i < r.size() - 1; ++i)
        {
            int roll = 0;

            if(counter < 100)
                roll = random_int(100 - counter);

            counter += roll;
            output.push_back(std::to_string(roll) + "% " + r[i]);
        }

        //push remaining
        output.push_back(std::to_string(100 - counter) + "% " + r.back());

        return output;
    }

    /// Runtime version (compile-time visitor pattern doesn't compile in msvc)
    std::vector<std::string> roll_value(weighted_value_t const& variant_val)
    {
        std::vector<std::string> output;

        if(auto* s = std::get_if<std::string>(&variant_val))
        {
            output.push_back(*s);
        }
        else if(auto* r = std::get_if<range_value_t>(&variant_val))
        {
            auto rolled_range = roll_range_value(*r);
            output.insert(output.end(), rolled_range.begin(), rolled_range.end());
        }
        else if(auto* m = std::get_if<multi_value_t>(&variant_val))
        {
            auto rolled_multi = roll_multi_value(*m);
            output.insert(output.end(), rolled_multi.begin(), rolled_multi.end());
        }
        else
        {
            EXPLODE("unexpected variant sub-type");
        }

        return output;
    }

    generated_node_t roll_values(value_list_t const& values, std::vector<pregen_node_t> const& value_nodes)
    {
        if(values.empty() && value_nodes.empty())
            return generated_node_t();

        uint32_t total = total_weight(values) + total_weight(value_nodes);

        int roll = random_int(total);

        for(size_t i = 0; i < values.size(); ++i)
        {
            if(roll <= values[i].weight)
            {
                generated_node_t node;
                node.generated_values = std::move(roll_value(values[i]));
                return node;
            }

            roll -= values[i].weight;
        }

        //if no value from the value list has been hit yet, continue onward into value_nodes
        for(size_t i = 0; i < value_nodes.size(); ++i)
        {
            if(roll <= value_nodes[i].weight)
            {
                generated_node_t node(value_nodes[i].name);
                //node.add_child(generate_node(value_nodes[i]));
                auto gend_node = generate_node(value_nodes[i]);
                node.add_value_node(std::move(gend_node));
                return node;
            }

            roll -= value_nodes[i].weight;
        }

        EXPLODE("Random roll was too large, ran out of values and value_nodes");
        return generated_node_t("ERROR");
    }

    generated_node_t roll_values(pregen_node_t const& node)
    {
        return roll_values(node.values, node.value_nodes);
    }

    pregen_node_t node_from_file(stdfs::path const& filepath)
    {
        using namespace std;

        auto ext = filepath.extension();
        if(ext == ".json")
        {
            return node_from_json(filepath);
        }
        else if(ext == ".yaml" || ext == ".yml")
        {
            cout << "TODO: yaml support";
            return pregen_node_t();
        }

        //TODO: exception?
        if(stdfs::is_directory(filepath))
            cout << filepath.string() << " is a directory, not a file";
        else
            cout << "Filetype " << ext << " not recognized";

        return pregen_node_t();
    }

    generated_node_t generate_node(pregen_node_t const& pre_node)
    {
        generated_node_t node;
        node.name = pre_node.name;

        for(auto const& child : pre_node.children)
        {
            node.add_child(generate_node(child));
        }

        if(pre_node.values.size() > 0 || pre_node.value_nodes.size() > 0)
        {
            generated_node_t rolled = roll_values(pre_node);
            node.merge_with(rolled);
        }

        auto search = pre_node.user_data.find("PrintString");
        if(search != pre_node.user_data.end())
        {
            node.print_string = std::get<std::string>(search->second);
        }

        return node;
    }

    generated_node_t generate_node_from_file(stdfs::path const& filepath)
    {
        auto node = node_from_file(filepath);
        return generate_node(node);
    }

    constexpr size_t indent_amt = 4;
    // constexpr char indent_char = ' ';
    // constexpr char indent_tree_marker = ':';
    constexpr char const* indent_cstr = ":   ";

    std::string indenation_string(size_t indent_level)
    {
        if(indent_level == 0)
            return "";

        // std::string indent_str(indent_level * indent_amt, indent_char);
        // indent_str[indent_str.size()-indent_amt] = indent_tree_marker;

        std::string indent_str;
        for(size_t i = 0; i < indent_level; ++i)
            indent_str.insert(indent_str.end(), indent_cstr, indent_cstr + 4);

        return indent_str;
    }

    void print_node(pregen_node_t const& node, size_t level)
    {
        using namespace std;

        auto indent = indenation_string(level);

        cout << indent << node.name << "\n";

        for(auto const& child : node.children)
            print_node(child, level + 1);

        indent.append(indenation_string(1));

        for(auto const& value : node.values)
            cout << indent << value << "\n";

        for(auto const& vnode : node.value_nodes)
            print_node(vnode, level + 1);

        for(auto const& user_vals : node.user_data)
            cout << indent << user_vals.first << ": " << user_vals.second << "\n";
    }

    void print_node(generated_node_t const& node, size_t level)
    {
        using namespace std;

        auto indent = indenation_string(level);

        cout << indent << node.name << "\n";

        for(auto const& child : node.children)
            print_node(child, level + 1);

        indent.append(indenation_string(1));

        for(auto const& value : node.generated_values)
            cout << indent << value << "\n";

        for(auto const& vn : node.value_nodes)
            print_node(vn, level + 1);
    }
}<|endoftext|>


<commit_before>//
//  WMSLayer.cpp
//  G3MiOSSDK
//
//  Created by José Miguel S N on 18/07/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "WMSLayer.hpp"
#include "Tile.hpp"
#include "Petition.hpp"

#include "IStringBuilder.hpp"
#include "LayerTilesRenderParameters.hpp"
#include "MercatorUtils.hpp"
#include "LayerCondition.hpp"

WMSLayer::WMSLayer(const std::string& mapLayer,
                   const URL& mapServerURL,
                   const WMSServerVersion mapServerVersion,
                   const std::string& queryLayer,
                   const URL& queryServerURL,
                   const WMSServerVersion queryServerVersion,
                   const Sector& sector,
                   const std::string& format,
                   const std::string& srs,
                   const std::string& style,
                   const bool isTransparent,
                   LayerCondition* condition,
                   const TimeInterval& timeToCache,
                   bool readExpired,
                   const LayerTilesRenderParameters* parameters):
Layer(condition,
      mapLayer,
      timeToCache,
      readExpired,
      (parameters == NULL)
      ? LayerTilesRenderParameters::createDefaultWGS84(Sector::fullSphere())
      : parameters),
_mapLayer(mapLayer),
_mapServerURL(mapServerURL),
_mapServerVersion(mapServerVersion),
_queryLayer(queryLayer),
_queryServerURL(queryServerURL),
_queryServerVersion(queryServerVersion),
_sector(sector),
_format(format),
_srs(srs),
_style(style),
_isTransparent(isTransparent),
_extraParameter("")
{

}

WMSLayer::WMSLayer(const std::string& mapLayer,
                   const URL& mapServerURL,
                   const WMSServerVersion mapServerVersion,
                   const Sector& sector,
                   const std::string& format,
                   const std::string& srs,
                   const std::string& style,
                   const bool isTransparent,
                   LayerCondition* condition,
                   const TimeInterval& timeToCache,
                   bool readExpired,
                   const LayerTilesRenderParameters* parameters):
Layer(condition,
      mapLayer,
      timeToCache,
      readExpired,
      (parameters == NULL)
      ? LayerTilesRenderParameters::createDefaultWGS84(Sector::fullSphere())
      : parameters),
_mapLayer(mapLayer),
_mapServerURL(mapServerURL),
_mapServerVersion(mapServerVersion),
_queryLayer(mapLayer),
_queryServerURL(mapServerURL),
_queryServerVersion(mapServerVersion),
_sector(sector),
_format(format),
_srs(srs),
_style(style),
_isTransparent(isTransparent),
_extraParameter("")
{

}

double WMSLayer::toBBOXLongitude(const Angle& longitude) const {
  return (_parameters->_mercator) ? MercatorUtils::longitudeToMeters(longitude) : longitude._degrees;
}

double WMSLayer::toBBOXLatitude(const Angle& latitude) const {
  return (_parameters->_mercator) ? MercatorUtils::latitudeToMeters(latitude) : latitude._degrees;
}

std::vector<Petition*> WMSLayer::createTileMapPetitions(const G3MRenderContext* rc,
                                                        const Tile* tile) const {
  std::vector<Petition*> petitions;

  const Sector tileSector = tile->_sector;
  if (!_sector.touchesWith(tileSector)) {
    return petitions;
  }

  const Sector sector = tileSector.intersection(_sector);
  if (sector._deltaLatitude.isZero() ||
      sector._deltaLongitude.isZero() ) {
    return petitions;
  }

  //TODO: MUST SCALE WIDTH,HEIGHT

  const Vector2I tileTextureResolution = _parameters->_tileTextureResolution;

	//Server name
  std::string req = _mapServerURL.getPath();
	if (req[req.size() - 1] != '?') {
		req += '?';
	}

  //  //If the server refer to itself as localhost...
  //  const int localhostPos = req.find("localhost");
  //  if (localhostPos != -1) {
  //    req = req.substr(localhostPos+9);
  //
  //    const int slashPos = req.find("/", 8);
  //    std::string newHost = req.substr(0, slashPos);
  //
  //    req = newHost + req;
  //  }

  req += "REQUEST=GetMap&SERVICE=WMS";

  switch (_mapServerVersion) {
    case WMS_1_3_0:
    {
      req += "&VERSION=1.3.0";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );

      req += isb->getString();
      delete isb;

      req += "&CRS=EPSG:4326";

      break;
    }
    case WMS_1_1_0:
    default:
    {
      // default is 1.1.1
      req += "&VERSION=1.1.1";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );

      req += isb->getString();
      delete isb;
      break;
    }
  }

  req += "&LAYERS=" + _mapLayer;

	req += "&FORMAT=" + _format;

  if (_srs != "") {
    req += "&SRS=" + _srs;
  }
	else {
    req += "&SRS=EPSG:4326";
  }

  //Style
  if (_style != "") {
    req += "&STYLES=" + _style;
  }
	else {
    req += "&STYLES=";
  }

  //ASKING TRANSPARENCY
  if (_isTransparent) {
    req += "&TRANSPARENT=TRUE";
  }
  else {
    req += "&TRANSPARENT=FALSE";
  }

  if (_extraParameter.compare("") != 0) {
    req += "&";
    req += _extraParameter;
  }

  //  printf("Request: %s\n", req.c_str());

  Petition *petition = new Petition(sector,
                                    URL(req, false),
                                    getTimeToCache(),
                                    getReadExpired(),
                                    _isTransparent);
  petitions.push_back(petition);

	return petitions;
}

URL WMSLayer::getFeatureInfoURL(const Geodetic2D& position,
                                const Sector& tileSector) const {
  if (!_sector.touchesWith(tileSector)) {
    return URL::nullURL();
  }

  const Sector sector = tileSector.intersection(_sector);

	//Server name
  std::string req = _queryServerURL.getPath();
	if (req[req.size()-1] != '?') {
		req += '?';
	}

  //If the server refer to itself as localhost...
  int pos = req.find("localhost");
  if (pos != -1) {
    req = req.substr(pos+9);

    int pos2 = req.find("/", 8);
    std::string newHost = req.substr(0, pos2);

    req = newHost + req;
  }

  req += "REQUEST=GetFeatureInfo&SERVICE=WMS";

  //SRS
  if (_srs != "") {
    req += "&SRS=" + _srs;
  }
	else {
    req += "&SRS=EPSG:4326";
  }

  switch (_queryServerVersion) {
    case WMS_1_3_0:
    {
      req += "&VERSION=1.3.0";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(_parameters->_tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(_parameters->_tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );

      req += isb->getString();

      delete isb;

      req += "&CRS=EPSG:4326";

      break;
    }
    case WMS_1_1_0:
    default:
    {
      // default is 1.1.1
      req += "&VERSION=1.1.1";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(_parameters->_tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(_parameters->_tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );

      req += isb->getString();

      delete isb;
      break;
    }
  }
  req += "&LAYERS=" + _queryLayer;
  req += "&QUERY_LAYERS=" + _queryLayer;

  req += "&INFO_FORMAT=text/plain";

  const IMathUtils* mu = IMathUtils::instance();

  double u;
  double v;
  if (_parameters->_mercator) {
    u = sector.getUCoordinate(position._longitude);
    v = MercatorUtils::getMercatorV(position._latitude);
  }
  else {
    const Vector2D uv = sector.getUVCoordinates(position);
    u = uv._x;
    v = uv._y;
  }

  //X and Y
  //const Vector2D uv = sector.getUVCoordinates(position);
  const long long x = mu->round( (u * _parameters->_tileTextureResolution._x) );
  const long long y = mu->round( (v * _parameters->_tileTextureResolution._y) );

  IStringBuilder* isb = IStringBuilder::newStringBuilder();
  isb->addString("&X=");
  isb->addLong(x);
  isb->addString("&Y=");
  isb->addLong(y);
  req += isb->getString();
  delete isb;

	return URL(req, false);
}

const std::string WMSLayer::description() const {
  return "[WMSLayer]";
}

bool WMSLayer::rawIsEquals(const Layer* that) const {
  WMSLayer* t = (WMSLayer*) that;

  if (!(_mapServerURL.isEquals(t->_mapServerURL))) {
    return false;
  }

  if (!(_queryServerURL.isEquals(t->_queryServerURL))) {
    return false;
  }

  if (_mapLayer != t->_mapLayer) {
    return false;
  }

  if (_mapServerVersion != t->_mapServerVersion) {
    return false;
  }

  if (_queryLayer != t->_queryLayer) {
    return false;
  }

  if (_queryServerVersion != t->_queryServerVersion) {
    return false;
  }

  if (!(_sector.isEquals(t->_sector))) {
    return false;
  }

  if (_format != t->_format) {
    return false;
  }

  if (_queryServerVersion != t->_queryServerVersion) {
    return false;
  }

  if (_srs != t->_srs) {
    return false;
  }

  if (_style != t->_style) {
    return false;
  }

  if (_isTransparent != t->_isTransparent) {
    return false;
  }

  if (_extraParameter != t->_extraParameter) {
    return false;
  }

  return true;
}

WMSLayer* WMSLayer::copy() const {
  return new WMSLayer(_mapLayer,
                      _mapServerURL,
                      _mapServerVersion,
                      _queryLayer,
                      _queryServerURL,
                      _queryServerVersion,
                      _sector,
                      _format,
                      _srs,
                      _style,
                      _isTransparent,
                      (_condition == NULL) ? NULL : _condition->copy(),
                      TimeInterval::fromMilliseconds(_timeToCacheMS),
                      _readExpired,
                      (_parameters == NULL) ? NULL : _parameters->copy());
}
<commit_msg>bug fixed in WMSLayer<commit_after>//
//  WMSLayer.cpp
//  G3MiOSSDK
//
//  Created by José Miguel S N on 18/07/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "WMSLayer.hpp"
#include "Tile.hpp"
#include "Petition.hpp"

#include "IStringBuilder.hpp"
#include "LayerTilesRenderParameters.hpp"
#include "MercatorUtils.hpp"
#include "LayerCondition.hpp"

WMSLayer::WMSLayer(const std::string& mapLayer,
                   const URL& mapServerURL,
                   const WMSServerVersion mapServerVersion,
                   const std::string& queryLayer,
                   const URL& queryServerURL,
                   const WMSServerVersion queryServerVersion,
                   const Sector& sector,
                   const std::string& format,
                   const std::string& srs,
                   const std::string& style,
                   const bool isTransparent,
                   LayerCondition* condition,
                   const TimeInterval& timeToCache,
                   bool readExpired,
                   const LayerTilesRenderParameters* parameters):
Layer(condition,
      mapLayer,
      timeToCache,
      readExpired,
      (parameters == NULL)
      ? LayerTilesRenderParameters::createDefaultWGS84(Sector::fullSphere())
      : parameters),
_mapLayer(mapLayer),
_mapServerURL(mapServerURL),
_mapServerVersion(mapServerVersion),
_queryLayer(queryLayer),
_queryServerURL(queryServerURL),
_queryServerVersion(queryServerVersion),
_sector(sector),
_format(format),
_srs(srs),
_style(style),
_isTransparent(isTransparent),
_extraParameter("")
{

}

WMSLayer::WMSLayer(const std::string& mapLayer,
                   const URL& mapServerURL,
                   const WMSServerVersion mapServerVersion,
                   const Sector& sector,
                   const std::string& format,
                   const std::string& srs,
                   const std::string& style,
                   const bool isTransparent,
                   LayerCondition* condition,
                   const TimeInterval& timeToCache,
                   bool readExpired,
                   const LayerTilesRenderParameters* parameters):
Layer(condition,
      mapLayer,
      timeToCache,
      readExpired,
      (parameters == NULL)
      ? LayerTilesRenderParameters::createDefaultWGS84(Sector::fullSphere())
      : parameters),
_mapLayer(mapLayer),
_mapServerURL(mapServerURL),
_mapServerVersion(mapServerVersion),
_queryLayer(mapLayer),
_queryServerURL(mapServerURL),
_queryServerVersion(mapServerVersion),
_sector(sector),
_format(format),
_srs(srs),
_style(style),
_isTransparent(isTransparent),
_extraParameter("")
{

}

double WMSLayer::toBBOXLongitude(const Angle& longitude) const {
  return (_parameters->_mercator) ? MercatorUtils::longitudeToMeters(longitude) : longitude._degrees;
}

double WMSLayer::toBBOXLatitude(const Angle& latitude) const {
  return (_parameters->_mercator) ? MercatorUtils::latitudeToMeters(latitude) : latitude._degrees;
}

std::vector<Petition*> WMSLayer::createTileMapPetitions(const G3MRenderContext* rc,
                                                        const Tile* tile) const {
  std::vector<Petition*> petitions;

  const std::string path = _mapServerURL.getPath();
  if (path.empty()) {
    return petitions;
  }

  const Sector tileSector = tile->_sector;
  if (!_sector.touchesWith(tileSector)) {
    return petitions;
  }

  const Sector sector = tileSector.intersection(_sector);
  if (sector._deltaLatitude.isZero() ||
      sector._deltaLongitude.isZero() ) {
    return petitions;
  }

  //TODO: MUST SCALE WIDTH,HEIGHT

  const Vector2I tileTextureResolution = _parameters->_tileTextureResolution;

	//Server name
  std::string req = path;
	if (req[req.size() - 1] != '?') {
		req += '?';
	}

  //  //If the server refer to itself as localhost...
  //  const int localhostPos = req.find("localhost");
  //  if (localhostPos != -1) {
  //    req = req.substr(localhostPos+9);
  //
  //    const int slashPos = req.find("/", 8);
  //    std::string newHost = req.substr(0, slashPos);
  //
  //    req = newHost + req;
  //  }

  req += "REQUEST=GetMap&SERVICE=WMS";

  switch (_mapServerVersion) {
    case WMS_1_3_0:
    {
      req += "&VERSION=1.3.0";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );

      req += isb->getString();
      delete isb;

      req += "&CRS=EPSG:4326";

      break;
    }
    case WMS_1_1_0:
    default:
    {
      // default is 1.1.1
      req += "&VERSION=1.1.1";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );

      req += isb->getString();
      delete isb;
      break;
    }
  }

  req += "&LAYERS=" + _mapLayer;

	req += "&FORMAT=" + _format;

  if (_srs != "") {
    req += "&SRS=" + _srs;
  }
	else {
    req += "&SRS=EPSG:4326";
  }

  //Style
  if (_style != "") {
    req += "&STYLES=" + _style;
  }
	else {
    req += "&STYLES=";
  }

  //ASKING TRANSPARENCY
  if (_isTransparent) {
    req += "&TRANSPARENT=TRUE";
  }
  else {
    req += "&TRANSPARENT=FALSE";
  }

  if (_extraParameter.compare("") != 0) {
    req += "&";
    req += _extraParameter;
  }

  //  printf("Request: %s\n", req.c_str());

  Petition *petition = new Petition(sector,
                                    URL(req, false),
                                    getTimeToCache(),
                                    getReadExpired(),
                                    _isTransparent);
  petitions.push_back(petition);

	return petitions;
}

URL WMSLayer::getFeatureInfoURL(const Geodetic2D& position,
                                const Sector& tileSector) const {
  if (!_sector.touchesWith(tileSector)) {
    return URL::nullURL();
  }

  const Sector sector = tileSector.intersection(_sector);

	//Server name
  std::string req = _queryServerURL.getPath();
	if (req[req.size()-1] != '?') {
		req += '?';
	}

  //If the server refer to itself as localhost...
  int pos = req.find("localhost");
  if (pos != -1) {
    req = req.substr(pos+9);

    int pos2 = req.find("/", 8);
    std::string newHost = req.substr(0, pos2);

    req = newHost + req;
  }

  req += "REQUEST=GetFeatureInfo&SERVICE=WMS";

  //SRS
  if (_srs != "") {
    req += "&SRS=" + _srs;
  }
	else {
    req += "&SRS=EPSG:4326";
  }

  switch (_queryServerVersion) {
    case WMS_1_3_0:
    {
      req += "&VERSION=1.3.0";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(_parameters->_tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(_parameters->_tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );

      req += isb->getString();

      delete isb;

      req += "&CRS=EPSG:4326";

      break;
    }
    case WMS_1_1_0:
    default:
    {
      // default is 1.1.1
      req += "&VERSION=1.1.1";

      IStringBuilder* isb = IStringBuilder::newStringBuilder();

      isb->addString("&WIDTH=");
      isb->addInt(_parameters->_tileTextureResolution._x);
      isb->addString("&HEIGHT=");
      isb->addInt(_parameters->_tileTextureResolution._y);

      isb->addString("&BBOX=");
      isb->addDouble( toBBOXLongitude( sector._lower._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._lower._latitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLongitude( sector._upper._longitude ) );
      isb->addString(",");
      isb->addDouble( toBBOXLatitude( sector._upper._latitude ) );

      req += isb->getString();

      delete isb;
      break;
    }
  }
  req += "&LAYERS=" + _queryLayer;
  req += "&QUERY_LAYERS=" + _queryLayer;

  req += "&INFO_FORMAT=text/plain";

  const IMathUtils* mu = IMathUtils::instance();

  double u;
  double v;
  if (_parameters->_mercator) {
    u = sector.getUCoordinate(position._longitude);
    v = MercatorUtils::getMercatorV(position._latitude);
  }
  else {
    const Vector2D uv = sector.getUVCoordinates(position);
    u = uv._x;
    v = uv._y;
  }

  //X and Y
  //const Vector2D uv = sector.getUVCoordinates(position);
  const long long x = mu->round( (u * _parameters->_tileTextureResolution._x) );
  const long long y = mu->round( (v * _parameters->_tileTextureResolution._y) );

  IStringBuilder* isb = IStringBuilder::newStringBuilder();
  isb->addString("&X=");
  isb->addLong(x);
  isb->addString("&Y=");
  isb->addLong(y);
  req += isb->getString();
  delete isb;

	return URL(req, false);
}

const std::string WMSLayer::description() const {
  return "[WMSLayer]";
}

bool WMSLayer::rawIsEquals(const Layer* that) const {
  WMSLayer* t = (WMSLayer*) that;

  if (!(_mapServerURL.isEquals(t->_mapServerURL))) {
    return false;
  }

  if (!(_queryServerURL.isEquals(t->_queryServerURL))) {
    return false;
  }

  if (_mapLayer != t->_mapLayer) {
    return false;
  }

  if (_mapServerVersion != t->_mapServerVersion) {
    return false;
  }

  if (_queryLayer != t->_queryLayer) {
    return false;
  }

  if (_queryServerVersion != t->_queryServerVersion) {
    return false;
  }

  if (!(_sector.isEquals(t->_sector))) {
    return false;
  }

  if (_format != t->_format) {
    return false;
  }

  if (_queryServerVersion != t->_queryServerVersion) {
    return false;
  }

  if (_srs != t->_srs) {
    return false;
  }

  if (_style != t->_style) {
    return false;
  }

  if (_isTransparent != t->_isTransparent) {
    return false;
  }

  if (_extraParameter != t->_extraParameter) {
    return false;
  }

  return true;
}

WMSLayer* WMSLayer::copy() const {
  return new WMSLayer(_mapLayer,
                      _mapServerURL,
                      _mapServerVersion,
                      _queryLayer,
                      _queryServerURL,
                      _queryServerVersion,
                      _sector,
                      _format,
                      _srs,
                      _style,
                      _isTransparent,
                      (_condition == NULL) ? NULL : _condition->copy(),
                      TimeInterval::fromMilliseconds(_timeToCacheMS),
                      _readExpired,
                      (_parameters == NULL) ? NULL : _parameters->copy());
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-pinocchio.
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio. If not, see <http://www.gnu.org/licenses/>.

#ifndef HPP_PINOCCHIO_LIEGROUP_ELEMENT_HH
# define HPP_PINOCCHIO_LIEGROUP_ELEMENT_HH

# include <hpp/pinocchio/liegroup-space.hh>
# include <hpp/pinocchio/deprecated.hh>

namespace hpp {
  namespace pinocchio {
    /// \addtogroup liegroup
    /// \{

    template <typename vector_type>
    class LiegroupElementBase
    {
    public:
      /// Constructor
      /// \param value vector representation,
      /// \param liegroupSpace space the element belongs to.
      template <typename Derived>
      LiegroupElementBase (const Eigen::EigenBase<Derived>& value,
                           const LiegroupSpacePtr_t& liegroupSpace) :
        value_ (value.derived()), space_ (liegroupSpace)
      {
        check();
      }

      /// Constructor
      /// \param value vector representation,
      ///
      /// By default the space containing the value is a vector space.
      template <typename Derived>
      explicit LiegroupElementBase (const Eigen::EigenBase<Derived>& value) :
        value_ (value.derived()),
        space_ (LiegroupSpace::create (value.derived().size ())) {}

      /// get reference to vector of Lie groups
      const LiegroupSpacePtr_t& space () const
      {
        return space_;
      }

      /// Const vector representation
      const vector_type& vector () const
      {
        return value_;
      }

      /// Size of the vector representation
      size_type size () const
      {
        return value_.size ();
      }

      /// Check that size of vector fits size of space
      /// \note only in debug mode
      void check () const
      {
        assert (value_.size () == space_->nq ());
      }

    protected:
      vector_type value_;
      LiegroupSpacePtr_t space_;
    };

    typedef LiegroupElementBase<vectorIn_t> LiegroupConstElementRef;

    template <typename vector_type>
    class LiegroupNonconstElementBase : public LiegroupElementBase<vector_type>
    {
      public:
        typedef LiegroupElementBase<vector_type> Base;

        /// Constructor
        /// \param value vector representation,
        /// \param liegroupSpace space the element belongs to.
        LiegroupNonconstElementBase (const vector_type& value,
                                     const LiegroupSpacePtr_t& space)
          : Base (value, space) {}

        /// Constructor
        /// \param value vector representation,
        ///
        /// By default the space containing the value is a vector space.
        LiegroupNonconstElementBase (const LiegroupSpacePtr_t& space) :
            Base (vector_t (space->nq ()), space) {}

        /// Constructor
        /// \param value vector representation,
        ///
        /// By default the space containing the value is a vector space.
        explicit LiegroupNonconstElementBase (const vector_type& value)
          : Base (value) {}

        /// Copy constructor
        template <typename vector_type2>
        LiegroupNonconstElementBase (const LiegroupElementBase<vector_type2>& other)
          : Base (other.vector(), other.space()) {}

        /// Const vector representation
        const vector_type& vector () const
        {
          return Base::vector();
        }

        /// Modifiable vector representation
        vector_type& vector ()
        {
          return this->value_;
        }

        /// Set element to neutral element
        void setNeutral ()
        {
          this->value_ = this->space_->neutral ().vector ();
        }

        /// Inplace integration of a velocity vector
        LiegroupNonconstElementBase& operator+= (vectorIn_t v);
    };

    /// Element of a Lie group
    ///
    /// See class LiegroupSpace.
    typedef LiegroupNonconstElementBase<   vector_t> LiegroupElement;
    typedef LiegroupNonconstElementBase<vectorOut_t> LiegroupElementRef;

    /// Integration of a velocity vector from a configuration
    ///
    /// \param e element of the Lie group,
    /// \param v element of the tangent space of the Lie group.
    /// \return the element of the Lie group resulting from the integration
    ///
    /// By extension of the vector space case, we represent the integration
    /// of a constant velocity during unit time by an addition
    template <typename vector_type>
    LiegroupElement operator+ (const LiegroupElementBase<vector_type>& e, vectorIn_t v);

    /// Difference between two configurations
    ///
    /// \param e1, e2 elements of the Lie group,
    /// \return the velocity that integrated from e2 yiels e1
    ///
    /// By extension of the vector space case, we represent the integration
    /// of a constant velocity during unit time by an addition
    template <typename vector_type1, typename vector_type2>
    vector_t operator- (const LiegroupElementBase<vector_type1>& e1, const LiegroupElementBase<vector_type2>& e2);
    /// \}

    /// Compute the log as a tangent vector of a Lie group element
    template <typename vector_type>
    vector_t log (const LiegroupElementBase<vector_type>& lge);

    template <typename vector_type>
    inline std::ostream& operator<< (std::ostream& os, const LiegroupElementBase<vector_type>& e)
    {
      os << "Lie group element in " << *(e.space ())
         << " represented by vector (" << e. vector ().transpose () << ")";
      return os;
    }
  } // namespace pinocchio
} // namespace hpp

#endif // HPP_PINOCCHIO_LIEGROUP_ELEMENT_HH
<commit_msg>Add missing empty constructor in LiegroupNonconstElementBase<commit_after>// Copyright (c) 2017, CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-pinocchio.
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio. If not, see <http://www.gnu.org/licenses/>.

#ifndef HPP_PINOCCHIO_LIEGROUP_ELEMENT_HH
# define HPP_PINOCCHIO_LIEGROUP_ELEMENT_HH

# include <hpp/pinocchio/liegroup-space.hh>
# include <hpp/pinocchio/deprecated.hh>

namespace hpp {
  namespace pinocchio {
    /// \addtogroup liegroup
    /// \{

    template <typename vector_type>
    class LiegroupElementBase
    {
    public:
      /// Constructor
      /// \param value vector representation,
      /// \param liegroupSpace space the element belongs to.
      template <typename Derived>
      LiegroupElementBase (const Eigen::EigenBase<Derived>& value,
                           const LiegroupSpacePtr_t& liegroupSpace) :
        value_ (value.derived()), space_ (liegroupSpace)
      {
        check();
      }

      /// Constructor
      /// \param value vector representation,
      ///
      /// By default the space containing the value is a vector space.
      template <typename Derived>
      explicit LiegroupElementBase (const Eigen::EigenBase<Derived>& value) :
        value_ (value.derived()),
        space_ (LiegroupSpace::create (value.derived().size ())) {}

      /// get reference to vector of Lie groups
      const LiegroupSpacePtr_t& space () const
      {
        return space_;
      }

      /// Const vector representation
      const vector_type& vector () const
      {
        return value_;
      }

      /// Size of the vector representation
      size_type size () const
      {
        return value_.size ();
      }

      /// Check that size of vector fits size of space
      /// \note only in debug mode
      void check () const
      {
        assert (value_.size () == space_->nq ());
      }

    protected:
      vector_type value_;
      LiegroupSpacePtr_t space_;
    };

    typedef LiegroupElementBase<vectorIn_t> LiegroupConstElementRef;

    template <typename vector_type>
    class LiegroupNonconstElementBase : public LiegroupElementBase<vector_type>
    {
      public:
        typedef LiegroupElementBase<vector_type> Base;

        /// Constructor
        /// \param value vector representation,
        /// \param liegroupSpace space the element belongs to.
        LiegroupNonconstElementBase (const vector_type& value,
                                     const LiegroupSpacePtr_t& space)
          : Base (value, space) {}

        /// Constructor
        /// \param value vector representation,
        ///
        /// By default the space containing the value is a vector space.
        LiegroupNonconstElementBase (const LiegroupSpacePtr_t& space) :
            Base (vector_t (space->nq ()), space) {}

        /// Constructor
        /// \param value vector representation,
        ///
        /// By default the space containing the value is a vector space.
        explicit LiegroupNonconstElementBase (const vector_type& value)
          : Base (value) {}

        /// Copy constructor
        template <typename vector_type2>
        LiegroupNonconstElementBase (const LiegroupElementBase<vector_type2>& other)
          : Base (other.vector(), other.space()) {}

        /// Constructor of trivial element
        LiegroupNonconstElementBase () : Base (vector_t(), LiegroupSpace::empty ()) {}

        /// Const vector representation
        const vector_type& vector () const
        {
          return Base::vector();
        }

        /// Modifiable vector representation
        vector_type& vector ()
        {
          return this->value_;
        }

        /// Set element to neutral element
        void setNeutral ()
        {
          this->value_ = this->space_->neutral ().vector ();
        }

        /// Inplace integration of a velocity vector
        LiegroupNonconstElementBase& operator+= (vectorIn_t v);
    };

    /// Element of a Lie group
    ///
    /// See class LiegroupSpace.
    typedef LiegroupNonconstElementBase<   vector_t> LiegroupElement;
    typedef LiegroupNonconstElementBase<vectorOut_t> LiegroupElementRef;

    /// Integration of a velocity vector from a configuration
    ///
    /// \param e element of the Lie group,
    /// \param v element of the tangent space of the Lie group.
    /// \return the element of the Lie group resulting from the integration
    ///
    /// By extension of the vector space case, we represent the integration
    /// of a constant velocity during unit time by an addition
    template <typename vector_type>
    LiegroupElement operator+ (const LiegroupElementBase<vector_type>& e, vectorIn_t v);

    /// Difference between two configurations
    ///
    /// \param e1, e2 elements of the Lie group,
    /// \return the velocity that integrated from e2 yiels e1
    ///
    /// By extension of the vector space case, we represent the integration
    /// of a constant velocity during unit time by an addition
    template <typename vector_type1, typename vector_type2>
    vector_t operator- (const LiegroupElementBase<vector_type1>& e1, const LiegroupElementBase<vector_type2>& e2);
    /// \}

    /// Compute the log as a tangent vector of a Lie group element
    template <typename vector_type>
    vector_t log (const LiegroupElementBase<vector_type>& lge);

    template <typename vector_type>
    inline std::ostream& operator<< (std::ostream& os, const LiegroupElementBase<vector_type>& e)
    {
      os << "Lie group element in " << *(e.space ())
         << " represented by vector (" << e. vector ().transpose () << ")";
      return os;
    }
  } // namespace pinocchio
} // namespace hpp

#endif // HPP_PINOCCHIO_LIEGROUP_ELEMENT_HH
<|endoftext|>


<commit_before>#include "ioutils.h"
#include "stringutils.h"
#include <iostream>
#include <math/infnan.h>
#include <fstream>
#include <limits>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

//if c is preceded by a \, returns the translated ascii character
int TranslateEscape(int c)
{
  switch(c) {
  case 'a':  return '\a';
  case 'b':  return '\b';
  case 'n':  return '\n';
  case 'r':  return '\r';
  case 't':  return '\t';
  case 'v':  return '\v';
  default:   return c;
  }
}

std::string TranslateEscapes(const std::string& str)
{
  std::string res;
  for(size_t i=0;i+1<str.length();i++) {
    if(str[i]=='\\') {
      res += TranslateEscape(str[i+1]);
      i++;
    }
    else res += str[i];
  }
  res += str[str.length()-1];
  return res;
}

void EatWhitespace(std::istream& in)
{
  while(in && isspace(in.peek())) in.get();
}

bool InputToken(std::istream& in,const char* characterSet,std::string& str)
{
  str.erase();
  int c;
  while(in && (c=in.peek())!=EOF) {
    if(strchr(characterSet,c) != NULL)
      str += c;
    c=in.get();
  }
  return !in.bad();
}

bool InputQuotedString(std::istream& in, char* out, int n)
{
  int c;
  int state=0;  //0 = not yet read begin ", 1 is reading chars until end "
  int i=0;
  while((c=in.peek())!=EOF) {
    switch (state) {
    case 0:
      if(c=='\"')
	state = 1;
      else if(!isspace(c)) return false;
      break;
    case 1:
      if(c=='\"') {
	in.get();
	out[i]='\0';
	return true;
      }
      else if(c=='\\') {
	c=in.get();
	c=in.peek();
	out[i] = c;
      }
      else {
	if(i>=n) return false;
	out[i] = c;
	i++;
      }
      break;
    }
    c=in.get();
  }
  return false;
}

bool InputQuotedString(std::istream& in, std::string& out)
{
  int c;
  int state=0;
  out.erase();
  while((c=in.peek())!=EOF) {
    switch (state) {
      case 0:
	if(c=='\"')
	  state = 1;
	else if(!isspace(c))
	  return false;
	break;
    case 1:
      if(c=='\"') { in.get(); return true; }
      else if(c=='\\') {
	c=in.get();
	c=in.peek();
	out+= c;
      }
      else
	out+= c;
      break;
    }
    c = in.get();
  }
  return false;
}

void OutputQuotedString(std::ostream& out, const char* str)
{
  if(StringContainsQuote(str)) {
    //output quotes using \"
    out<<'\"';
    const char* c=str;
    while(*c) {
      if(*c == '\"') out<<"\\\"";
      else out<<*c;
    }
    out<<'\"';
  }
  else
    out<<'\"'<<str<<'\"';
}

void OutputQuotedString(std::ostream& out, const std::string& str)
{
  OutputQuotedString(out,str.c_str());
}

bool StringContainsQuote(const char* str)
{
	return strchr(str,'\"')!=NULL;
}

bool StringContainsQuote(const std::string& str)
{
	return str.rfind('\"')!=str.npos;
}

bool StringRequiresQuoting(const char* str)
{
  if(*str == 0) return true;
  while(str) {
    if(!isgraph(*str)) return true;
    if(*str == '\"') return true;
    str++;
  }
  return false;
}

bool StringRequiresQuoting(const std::string& str)
{
  return StringRequiresQuoting(str.c_str());
}

bool SafeInputString(std::istream& in, char* str,int n)
{
  EatWhitespace(in);
  if(!in) return false;
  if(in.peek() == EOF) return false;
  if(in.peek() == '\"') return InputQuotedString(in,str,n);
  else { //read until new whitespace
    int i;
    for(i=0;i<n;i++) {
      str[i] = in.get();
      if(isspace(str[i]) || in.eof()) {
	str[i] = 0;
	return true;
      }
      if(!in) return false;
    }
    //buffer overflowed
    return false;
  }
}

bool SafeInputString(std::istream& in, std::string& str)
{
  //first eat up white space
  str.erase();
  while(in && isspace(in.peek())) in.get();
  if(!in) return false;
  if(in.peek() == EOF) return false;
  if(in.peek() == '\"') return InputQuotedString(in,str);
  else { //read until new whitespace
    in >> str;
    /*
    while(in) {
      char c = in.get();
      if(isspace(c) || c==EOF)
	return true;
      str += c;
    }
    */
    if(in.eof()) return true;
    if(!in) return false;
    return true;
  }
}

void SafeOutputString(std::ostream& out, const char* str)
{
  if(StringRequiresQuoting(str)) OutputQuotedString(out,str);
  else out<<str;
}

void SafeOutputString(std::ostream& out, const std::string& str)
{
  if(StringRequiresQuoting(str)) OutputQuotedString(out,str);
  else out<<str;
}

bool SafeInputFloat(std::istream& in, float& f)
{
  EatWhitespace(in);
  int c=in.peek();
  bool neg=false;
  if(c=='-') {
    in.get();
    c=in.peek();
    neg=true;
  }
  if(isdigit(c) || c=='.') { in>>f; }
  else if(tolower(c) == 'n' || tolower(c) == 'i') {
    std::string str;
    in>>str;
    Lowercase(str);
    if(str == "inf" || str == "infinity")
      f = Math::fInf;
    else if(str=="nan")
      f = std::numeric_limits<float>::quiet_NaN();
    else return false;
  }
  else return false;
  if(neg) f = -f;
  return (bool)in;
}

bool SafeInputFloat(std::istream& in, double& f)
{
  EatWhitespace(in);
  int c=in.peek();
  bool neg=false;
  if(c=='-') {
    in.get();
    c=in.peek();
    neg=true;
  }
#if _WIN32
  if(isdigit(c) || c=='.') { in>>f; }
#else
  if(std::isdigit(c) || c=='.') { in>>f; }
#endif
  else if(tolower(c) == 'n' || tolower(c) == 'i') {
    std::string str;
    in>>str;
    Lowercase(str);
    if(str == "inf" || str == "infinity")
      f = Math::dInf;
    else if(str=="nan")
      f = std::numeric_limits<double>::quiet_NaN();
    else return false;
  }
  else return false;
  if(neg) f = -f;
  return (bool)in;
}

bool SafeOutputFloat(std::ostream& out, float f)
{
  out<<f;
  return true;
}

bool SafeOutputFloat(std::ostream& out, double f)
{
  out<<f;
  return true;
}

bool GetFileContents(const char *filename,std::string& contents)
{
  std::ifstream in(filename, std::ios::in | std::ios::binary);
  if (in)
  {
    in.seekg(0, std::ios::end);
    contents.resize(in.tellg());
    in.seekg(0, std::ios::beg);
    in.read(&contents[0], contents.size());
    in.close();
    return true;
  }
  return false;
}
<commit_msg>Fixed stupid error in outputting quoted strings<commit_after>#include "ioutils.h"
#include "stringutils.h"
#include <iostream>
#include <math/infnan.h>
#include <fstream>
#include <limits>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

//if c is preceded by a \, returns the translated ascii character
int TranslateEscape(int c)
{
  switch(c) {
  case 'a':  return '\a';
  case 'b':  return '\b';
  case 'n':  return '\n';
  case 'r':  return '\r';
  case 't':  return '\t';
  case 'v':  return '\v';
  default:   return c;
  }
}

std::string TranslateEscapes(const std::string& str)
{
  std::string res;
  for(size_t i=0;i+1<str.length();i++) {
    if(str[i]=='\\') {
      res += TranslateEscape(str[i+1]);
      i++;
    }
    else res += str[i];
  }
  res += str[str.length()-1];
  return res;
}

void EatWhitespace(std::istream& in)
{
  while(in && isspace(in.peek())) in.get();
}

bool InputToken(std::istream& in,const char* characterSet,std::string& str)
{
  str.erase();
  int c;
  while(in && (c=in.peek())!=EOF) {
    if(strchr(characterSet,c) != NULL)
      str += c;
    c=in.get();
  }
  return !in.bad();
}

bool InputQuotedString(std::istream& in, char* out, int n)
{
  int c;
  int state=0;  //0 = not yet read begin ", 1 is reading chars until end "
  int i=0;
  while((c=in.peek())!=EOF) {
    switch (state) {
    case 0:
      if(c=='\"')
	state = 1;
      else if(!isspace(c)) return false;
      break;
    case 1:
      if(c=='\"') {
	in.get();
	out[i]='\0';
	return true;
      }
      else if(c=='\\') {
	c=in.get();
	c=in.peek();
	out[i] = c;
      }
      else {
	if(i>=n) return false;
	out[i] = c;
	i++;
      }
      break;
    }
    c=in.get();
  }
  return false;
}

bool InputQuotedString(std::istream& in, std::string& out)
{
  int c;
  int state=0;
  out.erase();
  while((c=in.peek())!=EOF) {
    switch (state) {
      case 0:
	if(c=='\"')
	  state = 1;
	else if(!isspace(c))
	  return false;
	break;
    case 1:
      if(c=='\"') { in.get(); return true; }
      else if(c=='\\') {
	c=in.get();
	c=in.peek();
	out+= c;
      }
      else
	out+= c;
      break;
    }
    c = in.get();
  }
  return false;
}

void OutputQuotedString(std::ostream& out, const char* str)
{
  if(StringContainsQuote(str)) {
    //output quotes using \"
    out<<'\"';
    const char* c=str;
    while(*c) {
      if(*c == '\"') out<<"\\\"";
      else out<<*c;
      c++;
    }
    out<<'\"';
  }
  else
    out<<'\"'<<str<<'\"';
}

void OutputQuotedString(std::ostream& out, const std::string& str)
{
  OutputQuotedString(out,str.c_str());
}

bool StringContainsQuote(const char* str)
{
	return strchr(str,'\"')!=NULL;
}

bool StringContainsQuote(const std::string& str)
{
	return str.rfind('\"')!=str.npos;
}

bool StringRequiresQuoting(const char* str)
{
  if(*str == 0) return true;
  while(str) {
    if(!isgraph(*str)) return true;
    if(*str == '\"') return true;
    str++;
  }
  return false;
}

bool StringRequiresQuoting(const std::string& str)
{
  return StringRequiresQuoting(str.c_str());
}

bool SafeInputString(std::istream& in, char* str,int n)
{
  EatWhitespace(in);
  if(!in) return false;
  if(in.peek() == EOF) return false;
  if(in.peek() == '\"') return InputQuotedString(in,str,n);
  else { //read until new whitespace
    int i;
    for(i=0;i<n;i++) {
      str[i] = in.get();
      if(isspace(str[i]) || in.eof()) {
	str[i] = 0;
	return true;
      }
      if(!in) return false;
    }
    //buffer overflowed
    return false;
  }
}

bool SafeInputString(std::istream& in, std::string& str)
{
  //first eat up white space
  str.erase();
  while(in && isspace(in.peek())) in.get();
  if(!in) return false;
  if(in.peek() == EOF) return false;
  if(in.peek() == '\"') return InputQuotedString(in,str);
  else { //read until new whitespace
    in >> str;
    /*
    while(in) {
      char c = in.get();
      if(isspace(c) || c==EOF)
	return true;
      str += c;
    }
    */
    if(in.eof()) return true;
    if(!in) return false;
    return true;
  }
}

void SafeOutputString(std::ostream& out, const char* str)
{
  if(StringRequiresQuoting(str)) OutputQuotedString(out,str);
  else out<<str;
}

void SafeOutputString(std::ostream& out, const std::string& str)
{
  if(StringRequiresQuoting(str)) OutputQuotedString(out,str);
  else out<<str;
}

bool SafeInputFloat(std::istream& in, float& f)
{
  EatWhitespace(in);
  int c=in.peek();
  bool neg=false;
  if(c=='-') {
    in.get();
    c=in.peek();
    neg=true;
  }
  if(isdigit(c) || c=='.') { in>>f; }
  else if(tolower(c) == 'n' || tolower(c) == 'i') {
    std::string str;
    in>>str;
    Lowercase(str);
    if(str == "inf" || str == "infinity")
      f = Math::fInf;
    else if(str=="nan")
      f = std::numeric_limits<float>::quiet_NaN();
    else return false;
  }
  else return false;
  if(neg) f = -f;
  return (bool)in;
}

bool SafeInputFloat(std::istream& in, double& f)
{
  EatWhitespace(in);
  int c=in.peek();
  bool neg=false;
  if(c=='-') {
    in.get();
    c=in.peek();
    neg=true;
  }
#if _WIN32
  if(isdigit(c) || c=='.') { in>>f; }
#else
  if(std::isdigit(c) || c=='.') { in>>f; }
#endif
  else if(tolower(c) == 'n' || tolower(c) == 'i') {
    std::string str;
    in>>str;
    Lowercase(str);
    if(str == "inf" || str == "infinity")
      f = Math::dInf;
    else if(str=="nan")
      f = std::numeric_limits<double>::quiet_NaN();
    else return false;
  }
  else return false;
  if(neg) f = -f;
  return (bool)in;
}

bool SafeOutputFloat(std::ostream& out, float f)
{
  out<<f;
  return true;
}

bool SafeOutputFloat(std::ostream& out, double f)
{
  out<<f;
  return true;
}

bool GetFileContents(const char *filename,std::string& contents)
{
  std::ifstream in(filename, std::ios::in | std::ios::binary);
  if (in)
  {
    in.seekg(0, std::ios::end);
    contents.resize(in.tellg());
    in.seekg(0, std::ios::beg);
    in.read(&contents[0], contents.size());
    in.close();
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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

#include "OgreCgPlugin.h"
#include "OgreRoot.h"
#include "OgreHighLevelGpuProgramManager.h"
#include "OgreCgFxScriptLoader.h"

namespace Ogre
{
	const String sPluginName = "Cg Program Manager";
	//---------------------------------------------------------------------
	CgPlugin::CgPlugin()
		:mCgProgramFactory(0)
	{

	}
	//---------------------------------------------------------------------
	const String& CgPlugin::getName() const
	{
		return sPluginName;
	}
	//---------------------------------------------------------------------
	void CgPlugin::install()
	{
	}
	//---------------------------------------------------------------------
	void CgPlugin::initialise()
	{
        // check for gles2 by the glsles factory (this plugin is not supported on embedded systems for now)
        if (HighLevelGpuProgramManager::getSingleton().isLanguageSupported("glsles") == false)
        {
            // Create new factory
            mCgProgramFactory = OGRE_NEW CgProgramFactory();

            // Register
            HighLevelGpuProgramManager::getSingleton().addFactory(mCgProgramFactory);

            OGRE_NEW CgFxScriptLoader();
        }
	}
	//---------------------------------------------------------------------
	void CgPlugin::shutdown()
	{
		// nothing to do
	}
	//---------------------------------------------------------------------
	void CgPlugin::uninstall()
	{
        if (mCgProgramFactory)
        {
			OGRE_DELETE CgFxScriptLoader::getSingletonPtr();

            // Remove from manager safely
            if (HighLevelGpuProgramManager::getSingletonPtr())
                HighLevelGpuProgramManager::getSingleton().removeFactory(mCgProgramFactory);
		    OGRE_DELETE mCgProgramFactory;
		    mCgProgramFactory = 0;
        }
	}
}
<commit_msg>[GL3+] Disable the Cg plugin during initialization. No more need to manually disable it in plugins.cfg.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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

#include "OgreCgPlugin.h"
#include "OgreRoot.h"
#include "OgreHighLevelGpuProgramManager.h"
#include "OgreCgFxScriptLoader.h"

namespace Ogre
{
	const String sPluginName = "Cg Program Manager";
	//---------------------------------------------------------------------
	CgPlugin::CgPlugin()
		:mCgProgramFactory(0)
	{

	}
	//---------------------------------------------------------------------
	const String& CgPlugin::getName() const
	{
		return sPluginName;
	}
	//---------------------------------------------------------------------
	void CgPlugin::install()
	{
	}
	//---------------------------------------------------------------------
	void CgPlugin::initialise()
	{
        // Cg is also not supported on OpenGL 3+
        if(Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL 3+") == String::npos)
        {
            LogManager::getSingleton().logMessage("Disabling Cg Plugin for GL3+");
            return;
        }

        // Check for gles2 by the glsles factory (this plugin is not supported on embedded systems for now)
        if (HighLevelGpuProgramManager::getSingleton().isLanguageSupported("glsles") == false)

        {
            // Create new factory
            mCgProgramFactory = OGRE_NEW CgProgramFactory();

            // Register
            HighLevelGpuProgramManager::getSingleton().addFactory(mCgProgramFactory);

            OGRE_NEW CgFxScriptLoader();
        }
	}
	//---------------------------------------------------------------------
	void CgPlugin::shutdown()
	{
		// nothing to do
	}
	//---------------------------------------------------------------------
	void CgPlugin::uninstall()
	{
        if (mCgProgramFactory)
        {
			OGRE_DELETE CgFxScriptLoader::getSingletonPtr();

            // Remove from manager safely
            if (HighLevelGpuProgramManager::getSingletonPtr())
                HighLevelGpuProgramManager::getSingleton().removeFactory(mCgProgramFactory);
		    OGRE_DELETE mCgProgramFactory;
		    mCgProgramFactory = 0;
        }
	}
}
<|endoftext|>


<commit_before>#pragma once

/**
 * \file sal/span.hpp
 *
 * Temporary partial std::span implementation until it is provided by
 * clang++, g++ and MSVC.
 */

#include <sal/config.hpp>
#include <iterator>
#include <type_traits>

__sal_begin

template <typename T>
class span_t
{
public:

  using element_type = T;
  using value_type = std::remove_cv_t<T>;
  using index_type = std::ptrdiff_t;
  using difference_type = std::ptrdiff_t;
  using pointer = T *;
  using reference = T &;
  using const_pointer = const T *;
  using const_reference = const T &;
  using iterator = pointer;
  using const_iterator = const_pointer;

  constexpr span_t () noexcept = default;
  constexpr span_t &operator= (const span_t &that) noexcept = default;

  constexpr span_t (pointer ptr, index_type count) noexcept
    : ptr_(ptr)
    , count_(count)
  { }

  constexpr span_t (pointer first, pointer last) noexcept
    : span_t(first, last - first)
  { }

  template <size_t N>
  constexpr span_t (element_type (&arr)[N]) noexcept
    : span_t(std::addressof(arr[0]), N)
  { }

  template <typename Container>
  constexpr span_t (Container &container)
    : span_t(std::data(container), std::size(container))
  { }

  template <typename Container>
  constexpr span_t (const Container &container)
    : span_t(std::data(container), std::size(container))
  { }

  constexpr bool empty () const noexcept
  {
    return size() == 0;
  }

  constexpr pointer data () const noexcept
  {
    return ptr_;
  }

  constexpr reference operator[] (index_type index) const
  {
    return ptr_[index];
  }

  constexpr index_type size () const noexcept
  {
    return count_;
  }

  constexpr index_type size_bytes () const noexcept
  {
    return size() * sizeof(element_type);
  }

  constexpr iterator begin () const noexcept
  {
    return ptr_;
  }

  constexpr const_iterator cbegin () const noexcept
  {
    return ptr_;
  }

  constexpr iterator end () const noexcept
  {
    return ptr_ + count_;
  }

  constexpr const_iterator cend () const noexcept
  {
    return ptr_ + count_;
  }

private:

  pointer ptr_{};
  size_t count_{};
};

template <typename T>
inline span_t<const std::byte> as_bytes (span_t<T> span) noexcept
{
  return {reinterpret_cast<const std::byte *>(span.data()), span.size_bytes()};
}

template <typename T, std::enable_if_t<std::is_const_v<T> == false, int> = 0>
inline span_t<std::byte> as_writable_bytes (span_t<T> span) noexcept
{
  return {reinterpret_cast<std::byte *>(span.data()), span.size_bytes()};
}

__sal_end
<commit_msg>Add doxygen docs for sal::span_t<commit_after>#pragma once

/**
 * \file sal/span.hpp
 *
 * Temporary partial std::span implementation until it is provided by
 * clang++, g++ and MSVC.
 */

#include <sal/config.hpp>
#include <iterator>
#include <type_traits>

__sal_begin

/**
 * \see https://en.cppreference.com/w/cpp/container/span
 */
template <typename T>
class span_t
{
public:

  /**
   * Span element type
   */
  using element_type = T;

  /**
   * Span value type
   */
  using value_type = std::remove_cv_t<T>;

  /**
   * Span index type
   */
  using index_type = std::ptrdiff_t;

  /**
   * Difference type between two span's pointer's
   */
  using difference_type = std::ptrdiff_t;

  /**
   * Span element pointer type
   */
  using pointer = T *;

  /**
   * Span element reference type
   */
  using reference = T &;

  /**
   * Span element const pointer type
   */
  using const_pointer = const T *;

  /**
   * Span element const reference type
   */
  using const_reference = const T &;

  /**
   * Span iterator type
   */
  using iterator = pointer;

  /**
   * Span const iterator type
   */
  using const_iterator = const_pointer;

  constexpr span_t () noexcept = default;

  /**
   * Assign \a that to \e this.
   */
  constexpr span_t &operator= (const span_t &that) noexcept = default;

  /**
   * Construct span over range [\a ptr, \a ptr + \a count)
   */
  constexpr span_t (pointer ptr, index_type count) noexcept
    : ptr_(ptr)
    , count_(count)
  { }

  /**
   * Construct span over range [\a first, \a last)
   */
  constexpr span_t (pointer first, pointer last) noexcept
    : span_t(first, last - first)
  { }

  /**
   * Construct span over \a arr
   */
  template <size_t N>
  constexpr span_t (element_type (&arr)[N]) noexcept
    : span_t(std::addressof(arr[0]), N)
  { }

  /**
   * Construct span over \a container
   */
  template <typename Container>
  constexpr span_t (Container &container)
    : span_t(std::data(container), std::size(container))
  { }

  /**
   * Construct const span over \a container
   */
  template <typename Container>
  constexpr span_t (const Container &container)
    : span_t(std::data(container), std::size(container))
  { }

  /**
   * Return true if size() == 0
   */
  constexpr bool empty () const noexcept
  {
    return size() == 0;
  }

  /**
   * Return pointer to beginning of span
   */
  constexpr pointer data () const noexcept
  {
    return ptr_;
  }

  /**
   * Return span element on \a index
   */
  constexpr reference operator[] (index_type index) const
  {
    return ptr_[index];
  }

  /**
   * Return number of elements in span
   */
  constexpr index_type size () const noexcept
  {
    return count_;
  }

  /**
   * Return size of span in bytes
   */
  constexpr index_type size_bytes () const noexcept
  {
    return size() * sizeof(element_type);
  }

  /**
   * Return iterator to beginning of span
   */
  constexpr iterator begin () const noexcept
  {
    return ptr_;
  }

  /**
   * Return const iterator to beginning of span
   */
  constexpr const_iterator cbegin () const noexcept
  {
    return ptr_;
  }

  /**
   * Return iterator to past end of span
   */
  constexpr iterator end () const noexcept
  {
    return ptr_ + count_;
  }

  /**
   * Return const iterator to past end of span
   */
  constexpr const_iterator cend () const noexcept
  {
    return ptr_ + count_;
  }

private:

  pointer ptr_{};
  size_t count_{};
};

/**
 * Return new const span with std::byte value type over existing \a span
 */
template <typename T>
inline span_t<const std::byte> as_bytes (span_t<T> span) noexcept
{
  return {reinterpret_cast<const std::byte *>(span.data()), span.size_bytes()};
}

/**
 * Return new span with std::byte value type over existing \a span
 */
template <typename T, std::enable_if_t<std::is_const_v<T> == false, int> = 0>
inline span_t<std::byte> as_writable_bytes (span_t<T> span) noexcept
{
  return {reinterpret_cast<std::byte *>(span.data()), span.size_bytes()};
}

__sal_end
<|endoftext|>