<commit_before>/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// subversion api
#include "svn_path.h"

// apr api
#include "apr_file_io.h"

// svncpp
#include "svnqt/path.hpp"
#include "svnqt/pool.hpp"
#include "svnqt/url.hpp"
#include "svnqt/svnqt_defines.hpp"

#include <qurl.h>

namespace svn
{
  Path::Path (const char * path)
  {
    init(QString::FROMUTF8(path));
  }

  Path::Path (const QString & path)
  {
    init (path);
  }

  Path::Path (const Path & path)
    : m_path(path.m_path)
  {
  }

  void
  Path::init (const QString& path)
  {
    Pool pool;

    if (path.isEmpty()) {
      m_path = "";
    } else {
      const char * int_path = svn_path_internal_style (path.TOUTF8(), pool.pool () );
      if (Url::isValid(path) ) {
        if (!svn_path_is_uri_safe(int_path)) {
            int_path = svn_path_uri_encode(int_path,pool);
        }
      }
      m_path = QString::FROMUTF8(int_path);
      if (Url::isValid(path) ) {
        /// @todo make sure that "@" is never used as revision paramter
        QUrl uri = m_path;
        m_path = uri.path();
        m_path.replace("@","%40");
        m_path = uri.protocol()+"://"+(uri.hasUser()?uri.user()+(uri.hasPassword()?":"+uri.hasPassword():"")+"@":"")
                +uri.host()+m_path;
        if (m_path.endsWith("/")) {
            int_path = svn_path_internal_style (path.TOUTF8(), pool.pool () );
            m_path = QString::FROMUTF8(int_path);
        }
      }
    }
  }

  const QString &
  Path::path () const
  {
    return m_path;
  }

  Path::operator const QString&()const
  {
    return m_path;
  }

  QString Path::prettyPath()const
  {
    if (!Url::isValid(m_path)) {
        return m_path;
    }
    Pool pool;
    const char * int_path = svn_path_uri_decode(m_path.TOUTF8(), pool.pool () );
    QString _p = QString::FROMUTF8(int_path);
    _p.replace("%40","@");
    return _p;
  }

  const QByteArray
  Path::cstr() const
  {
    return m_path.TOUTF8();
  }

  Path&
  Path::operator=(const Path & path)
  {
    if (this == &path)
      return *this;
    m_path = path.path();
    return *this;
  }

  bool
  Path::isset () const
  {
    return m_path.length () > 0;
  }

  void
  Path::addComponent (const QString& component)
  {
      Pool pool;

    if (Url::isValid (m_path))
    {
      const char * newPath =
          svn_path_url_add_component (m_path.TOUTF8(), component.TOUTF8(), pool);
      m_path = QString::FROMUTF8(newPath);
    }
    else
    {
      svn_stringbuf_t * pathStringbuf =
          svn_stringbuf_create (m_path.TOUTF8(), pool);

      svn_path_add_component (pathStringbuf,
                              component.TOUTF8());

      m_path = QString::FROMUTF8(pathStringbuf->data);
    }
  }

  void
  Path::addComponent (const char* component)
  {
    addComponent (QString::FROMUTF8(component));
  }

  void
  Path::split (QString & dirpath, QString & basename) const
  {
    Pool pool;

    const char * cdirpath;
    const char * cbasename;

    svn_path_split (m_path.TOUTF8(), &cdirpath, &cbasename, pool);
    dirpath = QString::FROMUTF8(cdirpath);
    basename = QString::FROMUTF8(cbasename);
  }

  void
  Path::split (QString & dir, QString & filename, QString & ext) const
  {
    QString basename;

    // first split path into dir and filename+ext
    split (dir, basename);

    // next search for last .
#if QT_VERSION < 0x040000
    int pos = basename.findRev(QChar('.'));
#else
    int pos = basename.lastIndexOf(QChar('.'));
#endif

    if (pos == -1)
    {
      filename = basename;
      ext = QString::fromLatin1("");
    }
    else
    {
      filename = basename.left(pos);
      ext = basename.mid(pos+1);
    }
  }

  Path
  Path::getTempDir ()
  {
    const char * tempdir = 0;
    Pool pool;

    if (apr_temp_dir_get (&tempdir, pool) != APR_SUCCESS)
    {
      tempdir = 0;
    }

    return tempdir;
  }

  unsigned int
  Path::length () const
  {
    return m_path.length ();
  }

  QString
  Path::native () const
  {
    Pool pool;

    return QString::FROMUTF8(svn_path_local_style (m_path.TOUTF8(), pool));
  }

}

/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../../rapidsvn-dev.el")
 * end:
 */
<commit_msg>ChangeLog updated Version increased  check for @ in svn::Path before replace-stuff<commit_after>/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// subversion api
#include "svn_path.h"

// apr api
#include "apr_file_io.h"

// svncpp
#include "svnqt/path.hpp"
#include "svnqt/pool.hpp"
#include "svnqt/url.hpp"
#include "svnqt/svnqt_defines.hpp"

#include <qurl.h>

namespace svn
{
  Path::Path (const char * path)
  {
    init(QString::FROMUTF8(path));
  }

  Path::Path (const QString & path)
  {
    init (path);
  }

  Path::Path (const Path & path)
    : m_path(path.m_path)
  {
  }

  void
  Path::init (const QString& path)
  {
    Pool pool;

    if (path.isEmpty()) {
      m_path = "";
    } else {
      const char * int_path = svn_path_internal_style (path.TOUTF8(), pool.pool () );
      if (Url::isValid(path) ) {
        if (!svn_path_is_uri_safe(int_path)) {
            int_path = svn_path_uri_encode(int_path,pool);
        }
      }
      m_path = QString::FROMUTF8(int_path);
      if (Url::isValid(path) && m_path.find("@")!=-1 ) {
        /// @todo make sure that "@" is never used as revision paramter
        QUrl uri = m_path;
        m_path = uri.path();
        m_path.replace("@","%40");
        m_path = uri.protocol()+"://"+(uri.hasUser()?uri.user()+(uri.hasPassword()?":"+uri.hasPassword():"")+"@":"")
                +uri.host()+m_path;
        if (m_path.endsWith("/")) {
            int_path = svn_path_internal_style (path.TOUTF8(), pool.pool () );
            m_path = QString::FROMUTF8(int_path);
        }
      }
    }
  }

  const QString &
  Path::path () const
  {
    return m_path;
  }

  Path::operator const QString&()const
  {
    return m_path;
  }

  QString Path::prettyPath()const
  {
    if (!Url::isValid(m_path)) {
        return m_path;
    }
    Pool pool;
    const char * int_path = svn_path_uri_decode(m_path.TOUTF8(), pool.pool () );
    QString _p = QString::FROMUTF8(int_path);
    _p.replace("%40","@");
    return _p;
  }

  const QByteArray
  Path::cstr() const
  {
    return m_path.TOUTF8();
  }

  Path&
  Path::operator=(const Path & path)
  {
    if (this == &path)
      return *this;
    m_path = path.path();
    return *this;
  }

  bool
  Path::isset () const
  {
    return m_path.length () > 0;
  }

  void
  Path::addComponent (const QString& component)
  {
      Pool pool;

    if (Url::isValid (m_path))
    {
      const char * newPath =
          svn_path_url_add_component (m_path.TOUTF8(), component.TOUTF8(), pool);
      m_path = QString::FROMUTF8(newPath);
    }
    else
    {
      svn_stringbuf_t * pathStringbuf =
          svn_stringbuf_create (m_path.TOUTF8(), pool);

      svn_path_add_component (pathStringbuf,
                              component.TOUTF8());

      m_path = QString::FROMUTF8(pathStringbuf->data);
    }
  }

  void
  Path::addComponent (const char* component)
  {
    addComponent (QString::FROMUTF8(component));
  }

  void
  Path::split (QString & dirpath, QString & basename) const
  {
    Pool pool;

    const char * cdirpath;
    const char * cbasename;

    svn_path_split (m_path.TOUTF8(), &cdirpath, &cbasename, pool);
    dirpath = QString::FROMUTF8(cdirpath);
    basename = QString::FROMUTF8(cbasename);
  }

  void
  Path::split (QString & dir, QString & filename, QString & ext) const
  {
    QString basename;

    // first split path into dir and filename+ext
    split (dir, basename);

    // next search for last .
#if QT_VERSION < 0x040000
    int pos = basename.findRev(QChar('.'));
#else
    int pos = basename.lastIndexOf(QChar('.'));
#endif

    if (pos == -1)
    {
      filename = basename;
      ext = QString::fromLatin1("");
    }
    else
    {
      filename = basename.left(pos);
      ext = basename.mid(pos+1);
    }
  }

  Path
  Path::getTempDir ()
  {
    const char * tempdir = 0;
    Pool pool;

    if (apr_temp_dir_get (&tempdir, pool) != APR_SUCCESS)
    {
      tempdir = 0;
    }

    return tempdir;
  }

  unsigned int
  Path::length () const
  {
    return m_path.length ();
  }

  QString
  Path::native () const
  {
    Pool pool;

    return QString::FROMUTF8(svn_path_local_style (m_path.TOUTF8(), pool));
  }

}

/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../../rapidsvn-dev.el")
 * end:
 */
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include "geojson_datasource.hpp"
#include "geojson_featureset.hpp"
#include "large_geojson_featureset.hpp"
#include <fstream>
#include <algorithm>

// boost
#include <boost/algorithm/string.hpp>
#include <boost/spirit/include/qi.hpp>

// mapnik
#include <mapnik/boolean.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/util/geometry_to_ds_type.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/util/file_io.hpp>
#include <mapnik/make_unique.hpp>
#include <mapnik/json/feature_collection_grammar.hpp>
#include <mapnik/json/extract_bounding_box_grammar_impl.hpp>
#include <mapnik/util/boost_geometry_adapters.hpp> // boost.geometry - register box2d<double>

using mapnik::datasource;
using mapnik::parameters;

DATASOURCE_PLUGIN(geojson_datasource)

struct attr_value_converter
{
    mapnik::eAttributeType operator() (mapnik::value_integer) const
    {
        return mapnik::Integer;
    }

    mapnik::eAttributeType operator() (double) const
    {
        return mapnik::Double;
    }

    mapnik::eAttributeType operator() (float) const
    {
        return mapnik::Double;
    }

    mapnik::eAttributeType operator() (bool) const
    {
        return mapnik::Boolean;
    }

    mapnik::eAttributeType operator() (std::string const& ) const
    {
        return mapnik::String;
    }

    mapnik::eAttributeType operator() (mapnik::value_unicode_string const&) const
    {
        return mapnik::String;
    }

    mapnik::eAttributeType operator() (mapnik::value_null const& ) const
    {
        return mapnik::String;
    }
};

geojson_datasource::geojson_datasource(parameters const& params)
  : datasource(params),
    type_(datasource::Vector),
    desc_(geojson_datasource::name(),
              *params.get<std::string>("encoding","utf-8")),
    filename_(),
    inline_string_(),
    extent_(),
    features_(),
    tree_(nullptr)
{
    boost::optional<std::string> inline_string = params.get<std::string>("inline");
    if (inline_string)
    {
        inline_string_ = *inline_string;
    }
    else
    {
        boost::optional<std::string> file = params.get<std::string>("file");
        if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: missing <file> parameter");

        boost::optional<std::string> base = params.get<std::string>("base");
        if (base)
            filename_ = *base + "/" + *file;
        else
            filename_ = *file;
    }
    if (!inline_string_.empty())
    {
        parse_geojson(inline_string_);
    }
    else
    {

        mapnik::util::file file(filename_);
        if (!file.open())
        {
            throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'");
        }

        std::string file_buffer;
        file_buffer.resize(file.size());
        std::fread(&file_buffer[0], file.size(), 1, file.get());
        cache_features_ = *params.get<mapnik::boolean_type>("cache_features", true);
        if (cache_features_)
        {
            parse_geojson(file_buffer);
        }
        else
        {
            initialise_index(file_buffer.begin(), file_buffer.end());
        }
    }
}

namespace {
using base_iterator_type = std::string::const_iterator;
const mapnik::transcoder tr("utf8");
const mapnik::json::feature_collection_grammar<base_iterator_type,mapnik::feature_impl> fc_grammar(tr);
}

template <typename Iterator>
void geojson_datasource::initialise_index(Iterator start, Iterator end)
{
    mapnik::json::boxes boxes;
    mapnik::json::extract_bounding_box_grammar<Iterator> bbox_grammar;
    boost::spirit::standard_wide::space_type space;
    if (!boost::spirit::qi::phrase_parse(start, end, (bbox_grammar)(boost::phoenix::ref(boxes)) , space))
    {
        throw mapnik::datasource_exception("GeoJSON Plugin: could not parse: '" + filename_ + "'");
    }
    std::cerr << "OK size=" << boxes.size() << std::endl;
    std::cerr << "Populate index" << std::endl;
#if BOOST_VERSION >= 105600
    tree_ = std::make_unique<spatial_index_type>(boxes);
#else
    tree_ = std::make_unique<spatial_index_type>(16, 4);
#endif
    std::cerr << "Calculate total extent" << std::endl;

    for (auto const& item : boxes)
    {
        auto const& box = std::get<0>(item);

#if BOOST_VERSION < 105600
        auto const& geometry_index = std::get<1>(item);
        tree_->insert(box, geometry_index);
#endif
        if (!extent_.valid())
        {
            extent_ = box;
        }
        else
        {
            extent_.expand_to_include(box);
        }
    }
    std::cerr << "Extent: " << extent_ << std::endl;
}

template <typename T>
void geojson_datasource::parse_geojson(T const& buffer)
{
    boost::spirit::standard_wide::space_type space;
    mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
    std::size_t start_id = 1;
    bool result = boost::spirit::qi::phrase_parse(buffer.begin(), buffer.end(), (fc_grammar)
                                                  (boost::phoenix::ref(ctx),boost::phoenix::ref(start_id)),
                                                  space, features_);
    if (!result)
    {
        if (!inline_string_.empty()) throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file from in-memory string");
        else throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file '" + filename_ + "'");
    }

#if BOOST_VERSION >= 105600
    using values_container = std::vector< std::pair<box_type, std::pair<std::size_t, std::size_t>>>;
    values_container values;
    values.reserve(features_.size());
#else
    tree_ = std::make_unique<spatial_index_type>(16, 4);
#endif

    std::size_t geometry_index = 0;
    for (mapnik::feature_ptr const& f : features_)
    {
        mapnik::box2d<double> box = f->envelope();
        if (box.valid())
        {
            if (geometry_index == 0)
            {
                extent_ = box;
                for ( auto const& kv : *f)
                {
                    desc_.add_descriptor(mapnik::attribute_descriptor(std::get<0>(kv),
                                                                      mapnik::util::apply_visitor(attr_value_converter(),
                                                                                std::get<1>(kv))));
                }
            }
            else
            {
                extent_.expand_to_include(box);
            }
        }
#if BOOST_VERSION >= 105600
        values.emplace_back(box, std::make_pair(geometry_index,0));
#else
        tree_->insert(box, std::make_pair(geometry_index));
#endif
        ++geometry_index;
    }

#if BOOST_VERSION >= 105600
    // packing algorithm
    tree_ = std::make_unique<spatial_index_type>(values);
#endif

}

geojson_datasource::~geojson_datasource() { }

const char * geojson_datasource::name()
{
    return "geojson";
}

boost::optional<mapnik::datasource::geometry_t> geojson_datasource::get_geometry_type() const
{
    boost::optional<mapnik::datasource::geometry_t> result;
    int multi_type = 0;
    unsigned num_features = features_.size();
    for (unsigned i = 0; i < num_features && i < 5; ++i)
    {
        mapnik::util::to_ds_type(features_[i]->paths(),result);
        if (result)
        {
            int type = static_cast<int>(*result);
            if (multi_type > 0 && multi_type != type)
            {
                result.reset(mapnik::datasource::Collection);
                return result;
            }
            multi_type = type;
        }
    }
    return result;
}

mapnik::datasource::datasource_t geojson_datasource::type() const
{
    return type_;
}

mapnik::box2d<double> geojson_datasource::envelope() const
{
    return extent_;
}

mapnik::layer_descriptor geojson_datasource::get_descriptor() const
{
    return desc_;
}

mapnik::featureset_ptr geojson_datasource::features(mapnik::query const& q) const
{
    // if the query box intersects our world extent then query for features
    mapnik::box2d<double> const& box = q.get_bbox();
    if (extent_.intersects(box))
    {
#if BOOST_VERSION >= 105600
        geojson_featureset::array_type index_array;
        if (tree_)
        {
            tree_->query(boost::geometry::index::intersects(box),std::back_inserter(index_array));

            if (cache_features_)
            {
                return std::make_shared<geojson_featureset>(features_, std::move(index_array));
            }
            else
            {
                std::cerr << "Query size=" << index_array.size() << std::endl;
                std::cerr << "Sort index_array by offsets" << std::endl;
                std::sort(index_array.begin(),index_array.end(),
                          [] (item_type const& item0, item_type const& item1)
                          {
                              return item0.second.first < item1.second.first;
                          });
                std::cerr << "Done" << std::endl;
                return std::make_shared<large_geojson_featureset>(filename_, std::move(index_array));
            }
        }
#else
        if (tree_)
        {
            if (cache_features_)
                return std::make_shared<geojson_featureset>(features_, tree_->find(box));
            else
                return std::make_shared<large_geojson_featureset>(features_, tree_->find(box));
        }
#endif
    }
    // otherwise return an empty featureset pointer
    return mapnik::featureset_ptr();
}

mapnik::featureset_ptr geojson_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const
{
    mapnik::box2d<double> query_bbox(pt, pt);
    query_bbox.pad(tol);
    mapnik::query q(query_bbox);
    std::vector<mapnik::attribute_descriptor> const& desc = desc_.get_descriptors();
    std::vector<mapnik::attribute_descriptor>::const_iterator itr = desc.begin();
    std::vector<mapnik::attribute_descriptor>::const_iterator end = desc.end();
    for ( ;itr!=end;++itr)
    {
        q.add_property_name(itr->get_name());
    }
    return features(q);
}
<commit_msg>extract attributes schema + remove std::cerr<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include "geojson_datasource.hpp"
#include "geojson_featureset.hpp"
#include "large_geojson_featureset.hpp"
#include <fstream>
#include <algorithm>

// boost
#include <boost/algorithm/string.hpp>
#include <boost/spirit/include/qi.hpp>

// mapnik
#include <mapnik/boolean.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/util/geometry_to_ds_type.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/util/file_io.hpp>
#include <mapnik/make_unique.hpp>
#include <mapnik/json/feature_collection_grammar.hpp>
#include <mapnik/json/extract_bounding_box_grammar_impl.hpp>
#include <mapnik/util/boost_geometry_adapters.hpp> // boost.geometry - register box2d<double>

using mapnik::datasource;
using mapnik::parameters;

DATASOURCE_PLUGIN(geojson_datasource)

struct attr_value_converter
{
    mapnik::eAttributeType operator() (mapnik::value_integer) const
    {
        return mapnik::Integer;
    }

    mapnik::eAttributeType operator() (double) const
    {
        return mapnik::Double;
    }

    mapnik::eAttributeType operator() (float) const
    {
        return mapnik::Double;
    }

    mapnik::eAttributeType operator() (bool) const
    {
        return mapnik::Boolean;
    }

    mapnik::eAttributeType operator() (std::string const& ) const
    {
        return mapnik::String;
    }

    mapnik::eAttributeType operator() (mapnik::value_unicode_string const&) const
    {
        return mapnik::String;
    }

    mapnik::eAttributeType operator() (mapnik::value_null const& ) const
    {
        return mapnik::String;
    }
};

geojson_datasource::geojson_datasource(parameters const& params)
  : datasource(params),
    type_(datasource::Vector),
    desc_(geojson_datasource::name(),
              *params.get<std::string>("encoding","utf-8")),
    filename_(),
    inline_string_(),
    extent_(),
    features_(),
    tree_(nullptr)
{
    boost::optional<std::string> inline_string = params.get<std::string>("inline");
    if (inline_string)
    {
        inline_string_ = *inline_string;
    }
    else
    {
        boost::optional<std::string> file = params.get<std::string>("file");
        if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: missing <file> parameter");

        boost::optional<std::string> base = params.get<std::string>("base");
        if (base)
            filename_ = *base + "/" + *file;
        else
            filename_ = *file;
    }
    if (!inline_string_.empty())
    {
        parse_geojson(inline_string_);
    }
    else
    {

        mapnik::util::file file(filename_);
        if (!file.open())
        {
            throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'");
        }

        std::string file_buffer;
        file_buffer.resize(file.size());
        std::fread(&file_buffer[0], file.size(), 1, file.get());
        cache_features_ = *params.get<mapnik::boolean_type>("cache_features", true);
        if (cache_features_)
        {
            parse_geojson(file_buffer);
        }
        else
        {
            initialise_index(file_buffer.begin(), file_buffer.end());
        }
    }
}

namespace {
using base_iterator_type = std::string::const_iterator;
const mapnik::transcoder tr("utf8");
const mapnik::json::feature_collection_grammar<base_iterator_type,mapnik::feature_impl> fc_grammar(tr);
}

template <typename Iterator>
void geojson_datasource::initialise_index(Iterator start, Iterator end)
{
    mapnik::json::boxes boxes;
    mapnik::json::extract_bounding_box_grammar<Iterator> bbox_grammar;
    boost::spirit::standard_wide::space_type space;
    if (!boost::spirit::qi::phrase_parse(start, end, (bbox_grammar)(boost::phoenix::ref(boxes)) , space))
    {
        throw mapnik::datasource_exception("GeoJSON Plugin: could not parse: '" + filename_ + "'");
    }
#if BOOST_VERSION >= 105600
    tree_ = std::make_unique<spatial_index_type>(boxes);
#else
    tree_ = std::make_unique<spatial_index_type>(16, 4);
#endif
    for (auto const& item : boxes)
    {
        auto const& box = std::get<0>(item);
        auto const& geometry_index = std::get<1>(item);
#if BOOST_VERSION < 105600
        tree_->insert(box, geometry_index);
#endif
        if (!extent_.valid())
        {
            extent_ = box;
            // parse first feature to extract attributes schema.
            // NOTE: this doesn't yield correct answer for geoJSON in general, just an indication
            mapnik::util::file file(filename_);
            if (!file.open())
            {
                throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'");
            }

            std::fseek(file.get(), geometry_index.first, SEEK_SET);
            std::vector<char> json;
            json.resize(geometry_index.second);
            std::fread(json.data(), geometry_index.second, 1, file.get());

            using chr_iterator_type = std::vector<char>::const_iterator;
            chr_iterator_type start = json.begin();
            chr_iterator_type end = json.end();

            mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
            mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
            using namespace boost::spirit;
            standard_wide::space_type space;
            if (!qi::phrase_parse(start, end, (fc_grammar.feature_g)(boost::phoenix::ref(*feature)), space))
            {
                throw std::runtime_error("Failed to parse geojson feature");
            }
            for ( auto const& kv : *feature)
            {
                desc_.add_descriptor(mapnik::attribute_descriptor(std::get<0>(kv),
                                                                  mapnik::util::apply_visitor(attr_value_converter(),
                                                                                std::get<1>(kv))));
            }
        }
        else
        {
            extent_.expand_to_include(box);
        }
    }
}

template <typename T>
void geojson_datasource::parse_geojson(T const& buffer)
{
    boost::spirit::standard_wide::space_type space;
    mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
    std::size_t start_id = 1;
    bool result = boost::spirit::qi::phrase_parse(buffer.begin(), buffer.end(), (fc_grammar)
                                                  (boost::phoenix::ref(ctx),boost::phoenix::ref(start_id)),
                                                  space, features_);
    if (!result)
    {
        if (!inline_string_.empty()) throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file from in-memory string");
        else throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file '" + filename_ + "'");
    }

#if BOOST_VERSION >= 105600
    using values_container = std::vector< std::pair<box_type, std::pair<std::size_t, std::size_t>>>;
    values_container values;
    values.reserve(features_.size());
#else
    tree_ = std::make_unique<spatial_index_type>(16, 4);
#endif

    std::size_t geometry_index = 0;
    for (mapnik::feature_ptr const& f : features_)
    {
        mapnik::box2d<double> box = f->envelope();
        if (box.valid())
        {
            if (geometry_index == 0)
            {
                extent_ = box;
                for ( auto const& kv : *f)
                {
                    desc_.add_descriptor(mapnik::attribute_descriptor(std::get<0>(kv),
                                                                      mapnik::util::apply_visitor(attr_value_converter(),
                                                                                std::get<1>(kv))));
                }
            }
            else
            {
                extent_.expand_to_include(box);
            }
        }
#if BOOST_VERSION >= 105600
        values.emplace_back(box, std::make_pair(geometry_index,0));
#else
        tree_->insert(box, std::make_pair(geometry_index));
#endif
        ++geometry_index;
    }

#if BOOST_VERSION >= 105600
    // packing algorithm
    tree_ = std::make_unique<spatial_index_type>(values);
#endif

}

geojson_datasource::~geojson_datasource() { }

const char * geojson_datasource::name()
{
    return "geojson";
}

boost::optional<mapnik::datasource::geometry_t> geojson_datasource::get_geometry_type() const
{
    boost::optional<mapnik::datasource::geometry_t> result;
    int multi_type = 0;
    unsigned num_features = features_.size();
    for (unsigned i = 0; i < num_features && i < 5; ++i)
    {
        mapnik::util::to_ds_type(features_[i]->paths(),result);
        if (result)
        {
            int type = static_cast<int>(*result);
            if (multi_type > 0 && multi_type != type)
            {
                result.reset(mapnik::datasource::Collection);
                return result;
            }
            multi_type = type;
        }
    }
    return result;
}

mapnik::datasource::datasource_t geojson_datasource::type() const
{
    return type_;
}

mapnik::box2d<double> geojson_datasource::envelope() const
{
    return extent_;
}

mapnik::layer_descriptor geojson_datasource::get_descriptor() const
{
    return desc_;
}

mapnik::featureset_ptr geojson_datasource::features(mapnik::query const& q) const
{
    // if the query box intersects our world extent then query for features
    mapnik::box2d<double> const& box = q.get_bbox();
    if (extent_.intersects(box))
    {
#if BOOST_VERSION >= 105600
        geojson_featureset::array_type index_array;
        if (tree_)
        {
            tree_->query(boost::geometry::index::intersects(box),std::back_inserter(index_array));

            if (cache_features_)
            {
                return std::make_shared<geojson_featureset>(features_, std::move(index_array));
            }
            else
            {
                std::sort(index_array.begin(),index_array.end(),
                          [] (item_type const& item0, item_type const& item1)
                          {
                              return item0.second.first < item1.second.first;
                          });
                return std::make_shared<large_geojson_featureset>(filename_, std::move(index_array));
            }
        }
#else
        if (tree_)
        {
            if (cache_features_)
                return std::make_shared<geojson_featureset>(features_, tree_->find(box));
            else
                return std::make_shared<large_geojson_featureset>(features_, tree_->find(box));
        }
#endif
    }
    // otherwise return an empty featureset pointer
    return mapnik::featureset_ptr();
}

mapnik::featureset_ptr geojson_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const
{
    mapnik::box2d<double> query_bbox(pt, pt);
    query_bbox.pad(tol);
    mapnik::query q(query_bbox);
    std::vector<mapnik::attribute_descriptor> const& desc = desc_.get_descriptors();
    std::vector<mapnik::attribute_descriptor>::const_iterator itr = desc.begin();
    std::vector<mapnik::attribute_descriptor>::const_iterator end = desc.end();
    for ( ;itr!=end;++itr)
    {
        q.add_property_name(itr->get_name());
    }
    return features(q);
}
<|endoftext|>


<commit_before>#include <Patcher/Patcher.hpp>

#include <Patcher/Config.hpp>
#include <Patcher/WebConnection.hpp>

#include <QProgressBar>
#include <QListWidgetItem>
#include <QLabel>
#include <QGroupBox>
#include <QScrollArea>
#include <QMessageBox>

#include <Patcher/Config.hpp>
#include <Patcher/Log.hpp>

#include <iostream>

#define ADD_ACTION(parent,var,str) QAction* var = new QAction(str,this);\
    parent->addAction(var);

#define ADD_MENU(parent,var,str) QMenu* var = parent->addMenu(str);

namespace patcher
{
    Patcher::Patcher(const std::string& soft) : QMainWindow(), maj_avalible(0)//, logList(nullptr)
    {
        patcher::Config::softname = soft;

         setWindowTitle(("Patcher - "+soft).c_str());
         initMenu();
         iniMainArea();
         soft_thread.setStandardOutputFile(("logs/"+soft+".txt").c_str(),QIODevice::Append);
         soft_thread.setStandardErrorFile(("logs/"+soft+".err.txt").c_str(),QIODevice::Append);
         QStringList env = QProcess::systemEnvironment();
         env<<"LD_LIBRARY_PATH=.";
         soft_thread.setEnvironment(env);
    }

    Patcher::~Patcher()
    {
    }

    void Patcher::start()
    {
        configMaj();
    }

    //// SLOTS //////
    void Patcher::showVersion()const
    {
        QMessageBox::information(nullptr,"Version","Version acctuelle:\n"+QString(Config::numberToString(Config::getVersion()).c_str()));
    }

    void Patcher::configSetUrl()const
    {
        Config::setUrl();
        Config::makeFile();
    }

    void Patcher::configMaj()
    {
        Config::init();
        patcher::WebConnection con;

        std::list<Log> logs;
        majs = con.getMaj(logs);
        //layout.clear();

        for(Log& log : logs)
        {
            QLabel* widget = new QLabel((log.getNumber()
                                           +": "
                                           +log.getMsg()).c_str());
            //widget->setMinimumSize(widget->minimumSizeHint());

            this->layout.addWidget(widget);

            std::cout<<log.getNumber()<<" "<<log.getMsg()<<std::endl;
        }

        maj_avalible = majs.size();

        if(maj_avalible > 0)
        {
            execMaj();
        }
    }

    void Patcher::configReset()const
    {
        Config::makeDefault();
    }

    void Patcher::runSoft()
    {
        QString name = QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QDir::separator() + Config::softname.c_str()).toString();
        #if __WIN32
            name +=".exe";
        #endif
        soft_thread.start(name);
    }

    void Patcher::quit()
    {
        if(soft_thread.state() == QProcess::Running)
        {
            QMessageBox::warning(nullptr,"Error",QString((Config::softname+" is running. Close it.").c_str()));
        }
        else
            qApp->quit();
    }

    ////////

    void Patcher::initMenu()
    {
        //Fichier
        QMenu* menuFichier  = menuBar()->addMenu("&Fichier");
        ///Quitter

        ADD_ACTION(menuFichier,actionRun,("Lancer" + Config::softname).c_str());
        connect(actionRun, SIGNAL(triggered()),this, SLOT(runSoft()));
        actionRun->setShortcut(QKeySequence("Ctrl+Enter"));

        ADD_ACTION(menuFichier,actionQuitter,"&Quitter");
        connect(actionQuitter, SIGNAL(triggered()),this, SLOT(quit()));
        actionQuitter->setShortcut(QKeySequence("Ctrl+Q"));
        //actionQuitter->setIcon(QIcon("quitter.png"));

        //Edition
        QMenu* menuEdition  = menuBar()->addMenu("&Edition");
        //actionGras->setCheckable(true);

        ADD_MENU(menuEdition,menuConfiguration,"&Configuration");

        ADD_ACTION(menuConfiguration,actionConfigurationUrl,"Definir l'url du site");
        connect(actionConfigurationUrl,SIGNAL(triggered()),this,SLOT(configSetUrl()));

        ADD_ACTION(menuConfiguration,actionConfigurationMaj,"Lancer une Maj");
        connect(actionConfigurationMaj,SIGNAL(triggered()),this,SLOT(configMaj()));
        actionConfigurationMaj->setShortcut(QKeySequence("F5"));

        ADD_ACTION(menuConfiguration,actionConfigurationReset,"Reset");
        connect(actionConfigurationReset,SIGNAL(triggered()),this,SLOT(configReset()));
        actionConfigurationReset->setShortcut(QKeySequence("Ctrl+L"));

        //Aide
        QMenu* menuAide     = menuBar()->addMenu("&Aide");
        ///Version
        ADD_ACTION(menuAide,actionVersion,"&Version")
        connect(actionVersion, SIGNAL(triggered()),this, SLOT(showVersion()));
    }

    void Patcher::iniMainArea()
    {
       QWidget* zoneCentrale = new QScrollArea;

       zoneCentrale->setLayout(&layout);
       setCentralWidget(zoneCentrale);
    }

    int Patcher::execMaj()
    {
        if (maj_avalible <= 0)
            return 0;

        QProgressBar progressBar;
        progressBar.setMaximumHeight(16);
        progressBar.setMaximumWidth(200);
        //progressBar->setTextVisible(false);
        progressBar.setRange(0,maj_avalible);
        this->statusBar()->addPermanentWidget(&progressBar, 0);
        this->statusBar()->showMessage(QString("Loading"));

        int nb = 0;
        int i = 1;
        for(patcher::Maj& maj : majs)
        {
            this->statusBar()->showMessage(QString("download "+QString::number(i)+"/"+QString::number(maj_avalible)));
            if(not maj.isDone())
                nb+= maj.apply();
            progressBar.setValue(++i);
        }

        this->statusBar()->clearMessage();
        this->statusBar()->removeWidget(&progressBar);

        return nb;
    }
}
<commit_msg>chage window size<commit_after>#include <Patcher/Patcher.hpp>

#include <Patcher/Config.hpp>
#include <Patcher/WebConnection.hpp>

#include <QProgressBar>
#include <QListWidgetItem>
#include <QLabel>
#include <QGroupBox>
#include <QScrollArea>
#include <QMessageBox>

#include <Patcher/Config.hpp>
#include <Patcher/Log.hpp>

#include <iostream>

#define ADD_ACTION(parent,var,str) QAction* var = new QAction(str,this);\
    parent->addAction(var);

#define ADD_MENU(parent,var,str) QMenu* var = parent->addMenu(str);

namespace patcher
{
    Patcher::Patcher(const std::string& soft) : QMainWindow(), maj_avalible(0)//, logList(nullptr)
    {
        patcher::Config::softname = soft;
        setFixedSize(400,300);

        setWindowTitle(("Patcher - "+soft).c_str());
        initMenu();
        iniMainArea();
        soft_thread.setStandardOutputFile(("logs/"+soft+".txt").c_str(),QIODevice::Append);
        soft_thread.setStandardErrorFile(("logs/"+soft+".err.txt").c_str(),QIODevice::Append);
        QStringList env = QProcess::systemEnvironment();
        env<<"LD_LIBRARY_PATH=.";
        soft_thread.setEnvironment(env);
    }

    Patcher::~Patcher()
    {
    }

    void Patcher::start()
    {
        configMaj();
    }

    //// SLOTS //////
    void Patcher::showVersion()const
    {
        QMessageBox::information(nullptr,"Version","Version acctuelle:\n"+QString(Config::numberToString(Config::getVersion()).c_str()));
    }

    void Patcher::configSetUrl()const
    {
        Config::setUrl();
        Config::makeFile();
    }

    void Patcher::configMaj()
    {
        Config::init();
        patcher::WebConnection con;

        std::list<Log> logs;
        majs = con.getMaj(logs);
        //layout.clear();

        for(Log& log : logs)
        {
            QLabel* widget = new QLabel((log.getNumber()
                                           +": "
                                           +log.getMsg()).c_str());
            //widget->setMinimumSize(widget->minimumSizeHint());

            this->layout.addWidget(widget);

            std::cout<<log.getNumber()<<" "<<log.getMsg()<<std::endl;
        }

        maj_avalible = majs.size();

        if(maj_avalible > 0)
        {
            execMaj();
        }
    }

    void Patcher::configReset()const
    {
        Config::makeDefault();
    }

    void Patcher::runSoft()
    {
        QString name = QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QDir::separator() + Config::softname.c_str()).toString();
        #if __WIN32
            name +=".exe";
        #endif
        soft_thread.start(name);
    }

    void Patcher::quit()
    {
        if(soft_thread.state() == QProcess::Running)
        {
            QMessageBox::warning(nullptr,"Error",QString((Config::softname+" is running. Close it.").c_str()));
        }
        else
            qApp->quit();
    }

    ////////

    void Patcher::initMenu()
    {
        //Fichier
        QMenu* menuFichier  = menuBar()->addMenu("&Fichier");
        ///Quitter

        ADD_ACTION(menuFichier,actionRun,("Lancer" + Config::softname).c_str());
        connect(actionRun, SIGNAL(triggered()),this, SLOT(runSoft()));
        actionRun->setShortcut(QKeySequence("Ctrl+Enter"));

        ADD_ACTION(menuFichier,actionQuitter,"&Quitter");
        connect(actionQuitter, SIGNAL(triggered()),this, SLOT(quit()));
        actionQuitter->setShortcut(QKeySequence("Ctrl+Q"));
        //actionQuitter->setIcon(QIcon("quitter.png"));

        //Edition
        QMenu* menuEdition  = menuBar()->addMenu("&Edition");
        //actionGras->setCheckable(true);

        ADD_MENU(menuEdition,menuConfiguration,"&Configuration");

        ADD_ACTION(menuConfiguration,actionConfigurationUrl,"Definir l'url du site");
        connect(actionConfigurationUrl,SIGNAL(triggered()),this,SLOT(configSetUrl()));

        ADD_ACTION(menuConfiguration,actionConfigurationMaj,"Lancer une Maj");
        connect(actionConfigurationMaj,SIGNAL(triggered()),this,SLOT(configMaj()));
        actionConfigurationMaj->setShortcut(QKeySequence("F5"));

        ADD_ACTION(menuConfiguration,actionConfigurationReset,"Reset");
        connect(actionConfigurationReset,SIGNAL(triggered()),this,SLOT(configReset()));
        actionConfigurationReset->setShortcut(QKeySequence("Ctrl+L"));

        //Aide
        QMenu* menuAide     = menuBar()->addMenu("&Aide");
        ///Version
        ADD_ACTION(menuAide,actionVersion,"&Version")
        connect(actionVersion, SIGNAL(triggered()),this, SLOT(showVersion()));
    }

    void Patcher::iniMainArea()
    {
       QWidget* zoneCentrale = new QScrollArea;

       zoneCentrale->setLayout(&layout);
       setCentralWidget(zoneCentrale);
    }

    int Patcher::execMaj()
    {
        if (maj_avalible <= 0)
            return 0;

        QProgressBar progressBar;
        progressBar.setMaximumHeight(16);
        progressBar.setMaximumWidth(200);
        //progressBar->setTextVisible(false);
        progressBar.setRange(0,maj_avalible);
        this->statusBar()->addPermanentWidget(&progressBar, 0);
        this->statusBar()->showMessage(QString("Loading"));

        int nb = 0;
        int i = 1;
        for(patcher::Maj& maj : majs)
        {
            this->statusBar()->showMessage(QString("download "+QString::number(i)+"/"+QString::number(maj_avalible)));
            if(not maj.isDone())
                nb+= maj.apply();
            progressBar.setValue(++i);
        }

        this->statusBar()->clearMessage();
        this->statusBar()->removeWidget(&progressBar);

        return nb;
    }
}
<|endoftext|>


<commit_before>#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <SOIL.h>

#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Shader.h"

GLfloat mix_value=0.2f;

glm::vec3 camera_position=glm::vec3(0.0f,0.0f,3.0f);
glm::vec3 camera_front=glm::vec3(0.0f,0.0f,-1.0f);
glm::vec3 camera_up=glm::vec3(0.0f,1.0f,0.0f);

void key_callback(GLFWwindow* window,int key,int scancode,int action,int mode)
{
    if(key==GLFW_KEY_ESCAPE && action==GLFW_PRESS)
        glfwSetWindowShouldClose(window,GL_TRUE);

    if(key==GLFW_KEY_UP && action==GLFW_PRESS)
    {
        mix_value+=0.1f;
        if(mix_value>1.0f) mix_value=1.0f;
    }

    if(key==GLFW_KEY_DOWN && action==GLFW_PRESS)
    {
        mix_value-=0.1f;
        if(mix_value<0.0f) mix_value=0.0f;
    }

    GLfloat camera_speed=0.05f;
    if(key==GLFW_KEY_W) camera_position+=camera_speed*camera_front;
    if(key==GLFW_KEY_S) camera_position-=camera_speed*camera_front;
    if(key==GLFW_KEY_A) camera_position-=glm::normalize(glm::cross(camera_front,camera_up))*camera_speed;
    if(key==GLFW_KEY_D) camera_position+=glm::normalize(glm::cross(camera_front,camera_up))*camera_speed;
}

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);

    GLFWwindow *window=glfwCreateWindow(800,600,"Learn OpenGL",nullptr,nullptr);
    if(window==nullptr)
    {
        std::cout<<"Failed to create GLFW window!"<<std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    glewExperimental=GL_TRUE;
    if(glewInit()!=GLEW_OK)
    {
        std::cout<<"Failed to initialize GLEW!"<<std::endl;
        return -1;
    }

    int width,height;
    glfwGetFramebufferSize(window,&width,&height);
    glViewport(0,0,width,height);

    // projection matrix
    glm::mat4 projection;
    projection=glm::perspective(glm::radians(45.0f),(float)width/height,0.1f,100.0f);

    glfwSetKeyCallback(window,key_callback);

    Shader our_shader("shader.vs","shader.frag");

    GLuint texture1,texture2;

    // generate texture 1
    glGenTextures(1,&texture1);
    glBindTexture(GL_TEXTURE_2D,texture1);
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    // set texture filtering
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    // load, create and generate mipmaps
    unsigned char* image=SOIL_load_image("container.jpg",&width,&height,0,SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,image);
    glGenerateMipmap(GL_TEXTURE_2D);
    // free image data
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D,0);

    // generate texture 2
    glGenTextures(1,&texture2);
    glBindTexture(GL_TEXTURE_2D,texture2);
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    // set texture filtering
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    // load, create and generate mipmaps
    image=SOIL_load_image("awesomeface.png",&width,&height,0,SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,image);
    glGenerateMipmap(GL_TEXTURE_2D);
    // free image data
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D,0);

    GLfloat vertices[]={
        // positions        // textures
        -0.5f,-0.5f,-0.5f,  0.0f,0.0f,
         0.5f,-0.5f,-0.5f,  1.0f,0.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
        -0.5f, 0.5f,-0.5f,  0.0f,1.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,0.0f,

        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,
         0.5f,-0.5f, 0.5f,  1.0f,0.0f,
         0.5f, 0.5f, 0.5f,  1.0f,1.0f,
         0.5f, 0.5f, 0.5f,  1.0f,1.0f,
        -0.5f, 0.5f, 0.5f,  0.0f,1.0f,
        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,

        -0.5f, 0.5f, 0.5f,  1.0f,0.0f,
        -0.5f, 0.5f,-0.5f,  1.0f,1.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,
        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,
        -0.5f, 0.5f, 0.5f,  1.0f,0.0f,

         0.5f, 0.5f, 0.5f,  1.0f,0.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
         0.5f,-0.5f,-0.5f,  0.0f,1.0f,
         0.5f,-0.5f,-0.5f,  0.0f,1.0f,
         0.5f,-0.5f, 0.5f,  0.0f,0.0f,
         0.5f, 0.5f, 0.5f,  1.0f,0.0f,

        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,
         0.5f,-0.5f,-0.5f,  1.0f,1.0f,
         0.5f,-0.5f, 0.5f,  1.0f,0.0f,
         0.5f,-0.5f, 0.5f,  1.0f,0.0f,
        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,

        -0.5f, 0.5f,-0.5f,  0.0f,1.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
         0.5f, 0.5f, 0.5f,  1.0f,0.0f,
         0.5f, 0.5f, 0.5f,  1.0f,0.0f,
        -0.5f, 0.5f, 0.5f,  0.0f,0.0f,
        -0.5f, 0.5f,-0.5f,  0.0f,1.0f
    };

    glm::vec3 cube_positions[]={
        glm::vec3( 0.0f, 0.0f, 0.0f),
        glm::vec3( 2.0f, 5.0f,-15.0f),
        glm::vec3(-1.5f,-2.2f,-2.5f),
        glm::vec3(-3.8f,-2.0f,-12.3f),
        glm::vec3( 2.4f,-0.4f,-3.5f),
        glm::vec3(-1.7f, 3.0f,-7.5f),
        glm::vec3( 1.3f,-2.0f,-2.5f),
        glm::vec3( 1.5f, 2.0f,-2.5f),
        glm::vec3( 1.5f, 0.2f,-1.5f),
        glm::vec3(-1.3f, 1.0f,-1.5f)
    };

    GLuint VAO,VBO;
    glGenBuffers(1,&VBO);
    glGenVertexArrays(1,&VAO);

    // bind vertex array object
    glBindVertexArray(VAO);

    // copy the vertices in a buffer
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    // set position attribute pointers
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(GL_FLOAT),(GLvoid*)0);
    glEnableVertexAttribArray(0);
    // set texture attribute pointers
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(GL_FLOAT),(GLvoid*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    // unbind the vertex array object
    glBindVertexArray(0);

    glEnable(GL_DEPTH_TEST);

    GLfloat radius=10.0f;

    while(!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        glClearColor(.2f,.3f,.3f,1.f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // use shader program
        our_shader.Use();

        // bind textures
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,texture1);
        glUniform1i(glGetUniformLocation(our_shader.program,"our_texture1"),0);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D,texture2);
        glUniform1i(glGetUniformLocation(our_shader.program,"our_texture2"),1);

        glUniform1f(glGetUniformLocation(our_shader.program,"mix_value"),mix_value);

        // view space transform
        glm::mat4 view=glm::lookAt(camera_position,camera_position+camera_front,camera_up);

        GLuint model_location=glGetUniformLocation(our_shader.program,"model");
        GLuint view_location=glGetUniformLocation(our_shader.program,"view");
        glUniformMatrix4fv(view_location,1,GL_FALSE,glm::value_ptr(view));
        GLuint projection_location=glGetUniformLocation(our_shader.program,"projection");
        glUniformMatrix4fv(projection_location,1,GL_FALSE,glm::value_ptr(projection));

        // draw
        glBindVertexArray(VAO);
        for(GLuint i=0;i<10;++i)
        {
            // world space transform
            glm::mat4 model;
            model=glm::translate(model,cube_positions[i]);
            model=glm::rotate(model,glm::radians((GLfloat)glfwGetTime()*50.0f),glm::vec3(0.5f,1.0f,0.0f));
            GLfloat angle=glm::radians(20.0f*i);
            model=glm::rotate(model,angle,glm::vec3(1.0f,0.3f,0.5f));
            glUniformMatrix4fv(model_location,1,GL_FALSE,glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES,0,36);
        }
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    // deallocate all resources
    glDeleteVertexArrays(1,&VAO);
    glDeleteBuffers(1,&VBO);
    // terminate GLFW
    glfwTerminate();

    return 0;
}
<commit_msg>hardware-independent smooth/uniform movement.<commit_after>#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <SOIL.h>

#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Shader.h"

GLfloat mix_value=0.2f;
bool keys[1024];
GLfloat delta_time=0.0f;    // time between current frame and last frame
GLfloat last_frame=0.0f;    // time of last frame

glm::vec3 camera_position=glm::vec3(0.0f,0.0f,3.0f);
glm::vec3 camera_front=glm::vec3(0.0f,0.0f,-1.0f);
glm::vec3 camera_up=glm::vec3(0.0f,1.0f,0.0f);

void do_movement()
{
    // camera controls
    GLfloat camera_speed=5.0f*delta_time;
    if(keys[GLFW_KEY_W]) camera_position+=camera_speed*camera_front;
    if(keys[GLFW_KEY_S]) camera_position-=camera_speed*camera_front;
    if(keys[GLFW_KEY_A]) camera_position-=glm::normalize(glm::cross(camera_front,camera_up))*camera_speed;
    if(keys[GLFW_KEY_D]) camera_position+=glm::normalize(glm::cross(camera_front,camera_up))*camera_speed;
}

void key_callback(GLFWwindow* window,int key,int scancode,int action,int mode)
{
    if(key==GLFW_KEY_ESCAPE && action==GLFW_PRESS)
        glfwSetWindowShouldClose(window,GL_TRUE);

    if(key==GLFW_KEY_UP && action==GLFW_PRESS)
    {
        mix_value+=0.1f;
        if(mix_value>1.0f) mix_value=1.0f;
    }

    if(key==GLFW_KEY_DOWN && action==GLFW_PRESS)
    {
        mix_value-=0.1f;
        if(mix_value<0.0f) mix_value=0.0f;
    }

    if(action==GLFW_PRESS) keys[key]=true;
    else if(action==GLFW_RELEASE) keys[key]=false;
}

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);

    GLFWwindow *window=glfwCreateWindow(800,600,"Learn OpenGL",nullptr,nullptr);
    if(window==nullptr)
    {
        std::cout<<"Failed to create GLFW window!"<<std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    glewExperimental=GL_TRUE;
    if(glewInit()!=GLEW_OK)
    {
        std::cout<<"Failed to initialize GLEW!"<<std::endl;
        return -1;
    }

    int width,height;
    glfwGetFramebufferSize(window,&width,&height);
    glViewport(0,0,width,height);

    // projection matrix
    glm::mat4 projection;
    projection=glm::perspective(glm::radians(45.0f),(float)width/height,0.1f,100.0f);

    glfwSetKeyCallback(window,key_callback);

    Shader our_shader("shader.vs","shader.frag");

    GLuint texture1,texture2;

    // generate texture 1
    glGenTextures(1,&texture1);
    glBindTexture(GL_TEXTURE_2D,texture1);
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    // set texture filtering
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    // load, create and generate mipmaps
    unsigned char* image=SOIL_load_image("container.jpg",&width,&height,0,SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,image);
    glGenerateMipmap(GL_TEXTURE_2D);
    // free image data
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D,0);

    // generate texture 2
    glGenTextures(1,&texture2);
    glBindTexture(GL_TEXTURE_2D,texture2);
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    // set texture filtering
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    // load, create and generate mipmaps
    image=SOIL_load_image("awesomeface.png",&width,&height,0,SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,image);
    glGenerateMipmap(GL_TEXTURE_2D);
    // free image data
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D,0);

    GLfloat vertices[]={
        // positions        // textures
        -0.5f,-0.5f,-0.5f,  0.0f,0.0f,
         0.5f,-0.5f,-0.5f,  1.0f,0.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
        -0.5f, 0.5f,-0.5f,  0.0f,1.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,0.0f,

        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,
         0.5f,-0.5f, 0.5f,  1.0f,0.0f,
         0.5f, 0.5f, 0.5f,  1.0f,1.0f,
         0.5f, 0.5f, 0.5f,  1.0f,1.0f,
        -0.5f, 0.5f, 0.5f,  0.0f,1.0f,
        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,

        -0.5f, 0.5f, 0.5f,  1.0f,0.0f,
        -0.5f, 0.5f,-0.5f,  1.0f,1.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,
        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,
        -0.5f, 0.5f, 0.5f,  1.0f,0.0f,

         0.5f, 0.5f, 0.5f,  1.0f,0.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
         0.5f,-0.5f,-0.5f,  0.0f,1.0f,
         0.5f,-0.5f,-0.5f,  0.0f,1.0f,
         0.5f,-0.5f, 0.5f,  0.0f,0.0f,
         0.5f, 0.5f, 0.5f,  1.0f,0.0f,

        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,
         0.5f,-0.5f,-0.5f,  1.0f,1.0f,
         0.5f,-0.5f, 0.5f,  1.0f,0.0f,
         0.5f,-0.5f, 0.5f,  1.0f,0.0f,
        -0.5f,-0.5f, 0.5f,  0.0f,0.0f,
        -0.5f,-0.5f,-0.5f,  0.0f,1.0f,

        -0.5f, 0.5f,-0.5f,  0.0f,1.0f,
         0.5f, 0.5f,-0.5f,  1.0f,1.0f,
         0.5f, 0.5f, 0.5f,  1.0f,0.0f,
         0.5f, 0.5f, 0.5f,  1.0f,0.0f,
        -0.5f, 0.5f, 0.5f,  0.0f,0.0f,
        -0.5f, 0.5f,-0.5f,  0.0f,1.0f
    };

    glm::vec3 cube_positions[]={
        glm::vec3( 0.0f, 0.0f, 0.0f),
        glm::vec3( 2.0f, 5.0f,-15.0f),
        glm::vec3(-1.5f,-2.2f,-2.5f),
        glm::vec3(-3.8f,-2.0f,-12.3f),
        glm::vec3( 2.4f,-0.4f,-3.5f),
        glm::vec3(-1.7f, 3.0f,-7.5f),
        glm::vec3( 1.3f,-2.0f,-2.5f),
        glm::vec3( 1.5f, 2.0f,-2.5f),
        glm::vec3( 1.5f, 0.2f,-1.5f),
        glm::vec3(-1.3f, 1.0f,-1.5f)
    };

    GLuint VAO,VBO;
    glGenBuffers(1,&VBO);
    glGenVertexArrays(1,&VAO);

    // bind vertex array object
    glBindVertexArray(VAO);

    // copy the vertices in a buffer
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    // set position attribute pointers
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(GL_FLOAT),(GLvoid*)0);
    glEnableVertexAttribArray(0);
    // set texture attribute pointers
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(GL_FLOAT),(GLvoid*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    // unbind the vertex array object
    glBindVertexArray(0);

    glEnable(GL_DEPTH_TEST);

    GLfloat radius=10.0f;

    while(!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        do_movement();
        glClearColor(.2f,.3f,.3f,1.f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        GLfloat current_frame=glfwGetTime();
        delta_time=current_frame-last_frame;
        last_frame=current_frame;

        // use shader program
        our_shader.Use();

        // bind textures
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,texture1);
        glUniform1i(glGetUniformLocation(our_shader.program,"our_texture1"),0);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D,texture2);
        glUniform1i(glGetUniformLocation(our_shader.program,"our_texture2"),1);

        glUniform1f(glGetUniformLocation(our_shader.program,"mix_value"),mix_value);

        // view space transform
        glm::mat4 view=glm::lookAt(camera_position,camera_position+camera_front,camera_up);

        GLuint model_location=glGetUniformLocation(our_shader.program,"model");
        GLuint view_location=glGetUniformLocation(our_shader.program,"view");
        glUniformMatrix4fv(view_location,1,GL_FALSE,glm::value_ptr(view));
        GLuint projection_location=glGetUniformLocation(our_shader.program,"projection");
        glUniformMatrix4fv(projection_location,1,GL_FALSE,glm::value_ptr(projection));

        // draw
        glBindVertexArray(VAO);
        for(GLuint i=0;i<10;++i)
        {
            // world space transform
            glm::mat4 model;
            model=glm::translate(model,cube_positions[i]);
            model=glm::rotate(model,glm::radians((GLfloat)glfwGetTime()*50.0f),glm::vec3(0.5f,1.0f,0.0f));
            GLfloat angle=glm::radians(20.0f*i);
            model=glm::rotate(model,angle,glm::vec3(1.0f,0.3f,0.5f));
            glUniformMatrix4fv(model_location,1,GL_FALSE,glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES,0,36);
        }
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    // deallocate all resources
    glDeleteVertexArrays(1,&VAO);
    glDeleteBuffers(1,&VBO);
    // terminate GLFW
    glfwTerminate();

    return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/uart_struct.h"

static const char *TAG = "MFRC522";

#define BUF_SIZE (1024)

#define NFC_UART_TXD  (16)
#define NFC_UART_RXD  (17)
#define NFC_UART_RTS  (18)
#define NFC_UART_CTS  (19)
QueueHandle_t uart2_queue;

#include "MFRC522.h"

//------------------MFRC522 register ---------------
#define         COMMAND_WAIT        0x02
#define         COMMAND_READBLOCK   0x03
#define         COMMAND_WRITEBLOCK  0x04
#define         MFRC522_HEADER      0xAB

#define         STATUS_ERROR        0
#define         STATUS_OK           1

#define         MIFARE_KEYA         0x00
#define         MIFARE_KEYB         0x01

/**
 * Constructor.
 */
MFRC522::MFRC522() {
}

/**
 * Description： Obtiene control del Serial para controlar MFRC522.
 * Ademas, pone MFRC522 en modo de espera.
 */
void MFRC522::begin(void) {
    uart_port_t uart_num = UART_NUM_2;
    uart_config_t uart_config = {
       .baud_rate = 9600,
       .data_bits = UART_DATA_8_BITS,
       .parity = UART_PARITY_DISABLE,
       .stop_bits = UART_STOP_BITS_1,
       .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
       .rx_flow_ctrl_thresh = 122,
    };
    //Set UART parameters
    uart_param_config(uart_num, &uart_config);
    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins,(-1: default pin, no change.)
    //For UART2, we can just use the default pins.
    uart_set_pin(uart_num, NFC_UART_TXD, NFC_UART_RXD, NFC_UART_RTS, NFC_UART_CTS);
    //Install UART driver, and get the queue.
    esp_err_t installed =  uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart2_queue, 0);
    printf("installed : %d\n", installed);
    wait();
}

/**
 * Description：Pone MFRC522 en modo espera.
 */
void MFRC522::wait() {
    write(COMMAND_WAIT);
}

/**
 * Description：Returns true if detect card in MFRC522.
 */
bool MFRC522::available() {
    return false;
}

/**
 * Description：Read the serial number of the card.
 */
void MFRC522::readCardSerial() {
    for (int i = 0; i < sizeof(cardSerial); ){
        if (available()){
            cardSerial[i] = read();
            i++;
        }
    }
}

/**
 * Description：Returns a pointer to array with card serial.
 */
byte *MFRC522::getCardSerial() {
    return cardSerial;
}

/**
 * Description：Read a block data of the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::getBlock(byte block, byte keyType, byte *key, byte *returnBlock) {
    byte sendData[8] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  // key
    };
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    return communicate(
        COMMAND_READBLOCK,  // command
        sendData,           // sendData
        0x0A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );
}

/**
 * Description：Write a block data in the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::writeBlock(byte block, byte keyType, byte *key, byte *data) {
    byte sendData[24] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // key
        0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Data
    };
    byte returnBlock[3];
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    for (int i = 0; i < 16; ++i) {
        sendData[8 + i] = data[i];
    }

    byte result = communicate(
        COMMAND_WRITEBLOCK, // command
        sendData,           // sendData
        0x1A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );

    return result;
}

/**
 * Description：Comunication between MFRC522 and ISO14443.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::communicate(byte command, byte *sendData, byte sendDataLength, byte *returnData, byte *returnDataLength) {
    // Send instruction to MFRC522
    write(MFRC522_HEADER);      // Header
    write(sendDataLength);      // Length (Length + Command + Data)
    write(command);             // Command

    for (int i = 0; i < sendDataLength - 2; i++) {
        write(sendData[i]);     // Data
    }

    // Read response to MFRC522
    while (!available());
    byte header = read();           // Header
    while (!available());
    *returnDataLength = read();     // Length (Length + Command + Data)
    while (!available());
    byte commandResult = read();    // Command result

    for (int i = 0; i < *returnDataLength - 2; i=i) {
        if (available()) {
            returnData[i] = read(); // Data
            i++;
        }
    }

    // Return
    if (command != commandResult) {
        return STATUS_ERROR;
    }

    return STATUS_OK;
}

/*
 * Description：Write a byte data into MFRC522.
 */
void MFRC522::write(byte value) {
    int uart_num = UART_NUM_2;
    uart_write_bytes(uart_num, (const char*)value, 1);
}

/*
 * Description：Read a byte data of MFRC522
 * Return：Return the read value.
 */
byte MFRC522::read() {
    uart_port_t uart_num = UART_NUM_2;
    uint8_t *data = (uint8_t *)malloc(1);
    TickType_t ticks_to_wait = portTICK_RATE_MS;
    uart_read_bytes(uart_num,data,1,ticks_to_wait);
    return *data;
}
<commit_msg>Update MFRC522.cpp<commit_after>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/uart_struct.h"

static const char *TAG = "MFRC522";

#define BUF_SIZE (1024)

#define NFC_UART_TXD  (16)
#define NFC_UART_RXD  (17)
#define NFC_UART_RTS  (18)
#define NFC_UART_CTS  (19)
QueueHandle_t uart2_queue;

#include "MFRC522.h"

//------------------MFRC522 register ---------------
#define         COMMAND_WAIT        0x02
#define         COMMAND_READBLOCK   0x03
#define         COMMAND_WRITEBLOCK  0x04
#define         MFRC522_HEADER      0xAB

#define         STATUS_ERROR        0
#define         STATUS_OK           1

#define         MIFARE_KEYA         0x00
#define         MIFARE_KEYB         0x01

/**
 * Constructor.
 */
MFRC522::MFRC522() {
}

/**
 * Description： Obtiene control del Serial para controlar MFRC522.
 * Ademas, pone MFRC522 en modo de espera.
 */
void MFRC522::begin(void) {
    uart_port_t uart_num = UART_NUM_2;
    uart_config_t uart_config = {
       .baud_rate = 9600,
       .data_bits = UART_DATA_8_BITS,
       .parity = UART_PARITY_DISABLE,
       .stop_bits = UART_STOP_BITS_1,
       .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
       .rx_flow_ctrl_thresh = 122,
    };
    //Set UART parameters
    uart_param_config(uart_num, &uart_config);
    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins,(-1: default pin, no change.)
    //For UART2, we can just use the default pins.
    uart_set_pin(uart_num, NFC_UART_TXD, NFC_UART_RXD, NFC_UART_RTS, NFC_UART_CTS);
    //Install UART driver, and get the queue.
    esp_err_t installed =  uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart2_queue, 0);
    printf("installed : %d\n", installed);
    wait();
}

/**
 * Description：Pone MFRC522 en modo espera.
 */
void MFRC522::wait() {
    write(COMMAND_WAIT);
}

/**
 * Description：Returns true if detect card in MFRC522.
 */
bool MFRC522::available() {
    return false;
}

/**
 * Description：Read the serial number of the card.
 */
void MFRC522::readCardSerial() {
    for (int i = 0; i < sizeof(cardSerial); ){
        if (available()){
            cardSerial[i] = read();
            i++;
        }
    }
}

/**
 * Description：Returns a pointer to array with card serial.
 */
byte *MFRC522::getCardSerial() {
    return cardSerial;
}

/**
 * Description：Read a block data of the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::getBlock(byte block, byte keyType, byte *key, byte *returnBlock) {
    byte sendData[8] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  // key
    };
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    return communicate(
        COMMAND_READBLOCK,  // command
        sendData,           // sendData
        0x0A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );
}

/**
 * Description：Write a block data in the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::writeBlock(byte block, byte keyType, byte *key, byte *data) {
    byte sendData[24] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // key
        0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Data
    };
    byte returnBlock[3];
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    for (int i = 0; i < 16; ++i) {
        sendData[8 + i] = data[i];
    }

    byte result = communicate(
        COMMAND_WRITEBLOCK, // command
        sendData,           // sendData
        0x1A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );

    return result;
}

/**
 * Description：Comunication between MFRC522 and ISO14443.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::communicate(byte command, byte *sendData, byte sendDataLength, byte *returnData, byte *returnDataLength) {
    // Send instruction to MFRC522
    write(MFRC522_HEADER);      // Header
    write(sendDataLength);      // Length (Length + Command + Data)
    write(command);             // Command

    for (int i = 0; i < sendDataLength - 2; i++) {
        write(sendData[i]);     // Data
    }

    // Read response to MFRC522
    while (!available());
    byte header = read();           // Header
    while (!available());
    *returnDataLength = read();     // Length (Length + Command + Data)
    while (!available());
    byte commandResult = read();    // Command result

    for (int i = 0; i < *returnDataLength - 2; i=i) {
        if (available()) {
            returnData[i] = read(); // Data
            i++;
        }
    }

    // Return
    if (command != commandResult) {
        return STATUS_ERROR;
    }

    return STATUS_OK;
}

/*
 * Description：Write a byte data into MFRC522.
 */
void MFRC522::write(byte value) {
    uart_port_t uart_num = UART_NUM_2;
    uart_write_bytes(uart_num, (const char*)value, 1);
}

/*
 * Description：Read a byte data of MFRC522
 * Return：Return the read value.
 */
byte MFRC522::read() {
    uart_port_t uart_num = UART_NUM_2;
    uint8_t *data = (uint8_t *)malloc(1);
    TickType_t ticks_to_wait = portTICK_RATE_MS;
    uart_read_bytes(uart_num,data,1,ticks_to_wait);
    return *data;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/uart_struct.h"

static const char *TAG = "MFRC522";

#define BUF_SIZE (1024)

#define NFC_UART_TXD  (16)
#define NFC_UART_RXD  (17)
#define NFC_UART_RTS  (18)
#define NFC_UART_CTS  (19)
QueueHandle_t uart2_queue;

#include "MFRC522.h"

//------------------MFRC522 register ---------------
#define         COMMAND_WAIT        0x02
#define         COMMAND_READBLOCK   0x03
#define         COMMAND_WRITEBLOCK  0x04
#define         MFRC522_HEADER      0xAB

#define         STATUS_ERROR        0
#define         STATUS_OK           1

#define         MIFARE_KEYA         0x00
#define         MIFARE_KEYB         0x01

/**
 * Constructor.
 */
MFRC522::MFRC522() {
}

/**
 * Description： Obtiene control del Serial para controlar MFRC522.
 * Ademas, pone MFRC522 en modo de espera.
 */
void MFRC522::begin(void) {
    uart_port_t uart_num = UART_NUM_2;
    uart_config_t uart_config = {
       .baud_rate = 9600,
       .data_bits = UART_DATA_8_BITS,
       .parity = UART_PARITY_DISABLE,
       .stop_bits = UART_STOP_BITS_1,
       .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
       .rx_flow_ctrl_thresh = 122,
    };
    //Set UART parameters
    uart_param_config(uart_num, &uart_config);
    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins,(-1: default pin, no change.)
    //For UART2, we can just use the default pins.
    uart_set_pin(uart_num, NFC_UART_TXD, NFC_UART_RXD, NFC_UART_RTS, NFC_UART_CTS);
    //Install UART driver, and get the queue.
    esp_err_t installed =  uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart2_queue, 0);
    printf("installed : %d\n", installed);
    wait();
}

/**
 * Description：Pone MFRC522 en modo espera.
 */
void MFRC522::wait() {
    write(COMMAND_WAIT);
}

/**
 * Description：Returns true if detect card in MFRC522.
 */
bool MFRC522::available() {
    return false;
}

/**
 * Description：Read the serial number of the card.
 */
void MFRC522::readCardSerial() {
    for (int i = 0; i < sizeof(cardSerial); ){
        if (available()){
            cardSerial[i] = read();
            i++;
        }
    }
}

/**
 * Description：Returns a pointer to array with card serial.
 */
byte *MFRC522::getCardSerial() {
    return cardSerial;
}

/**
 * Description：Read a block data of the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::getBlock(byte block, byte keyType, byte *key, byte *returnBlock) {
    byte sendData[8] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  // key
    };
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    return communicate(
        COMMAND_READBLOCK,  // command
        sendData,           // sendData
        0x0A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );
}

/**
 * Description：Write a block data in the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::writeBlock(byte block, byte keyType, byte *key, byte *data) {
    byte sendData[24] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // key
        0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Data
    };
    byte returnBlock[3];
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    for (int i = 0; i < 16; ++i) {
        sendData[8 + i] = data[i];
    }

    byte result = communicate(
        COMMAND_WRITEBLOCK, // command
        sendData,           // sendData
        0x1A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );

    return result;
}

/**
 * Description：Comunication between MFRC522 and ISO14443.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::communicate(byte command, byte *sendData, byte sendDataLength, byte *returnData, byte *returnDataLength) {
    // Send instruction to MFRC522
    write(MFRC522_HEADER);      // Header
    write(sendDataLength);      // Length (Length + Command + Data)
    write(command);             // Command

    for (int i = 0; i < sendDataLength - 2; i++) {
        write(sendData[i]);     // Data
    }

    // Read response to MFRC522
    while (!available());
    byte header = read();           // Header
    while (!available());
    *returnDataLength = read();     // Length (Length + Command + Data)
    while (!available());
    byte commandResult = read();    // Command result

    for (int i = 0; i < *returnDataLength - 2; i=i) {
        if (available()) {
            returnData[i] = read(); // Data
            i++;
        }
    }

    // Return
    if (command != commandResult) {
        return STATUS_ERROR;
    }

    return STATUS_OK;
}

/*
 * Description：Write a byte data into MFRC522.
 */
void MFRC522::write(byte value) {
    uart_port_t uart_num = UART_NUM_2;
    uart_write_bytes(uart_num, (const char*)value, 1);
}

/*
 * Description：Read a byte data of MFRC522
 * Return：Return the read value.
 */
byte MFRC522::read() {
    uart_port_t uart_num = UART_NUM_2;
    uint8_t *data = (uint8_t *)malloc(1);
    TickType_t ticks_to_wait = portTICK_RATE_MS;
    uart_read_bytes(uart_num,data,1,ticks_to_wait);
    return *data;
}

extern "C" void MFRC522_main() {
    MFRC522 Conector;
    Conector.begin();
    printf("begin :\n");
    //while(true)
    {
        //Conector.readCardSerial();
        printf("readCardSerial :\n");
        Conector.wait();
    }
}
<commit_msg>Update MFRC522.cpp<commit_after>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/uart_struct.h"

static const char *TAG = "MFRC522";

#define BUF_SIZE (1024)

#define NFC_UART_TXD  (16)
#define NFC_UART_RXD  (17)
#define NFC_UART_RTS  (18)
#define NFC_UART_CTS  (19)
QueueHandle_t uart2_queue;

#include "MFRC522.h"

//------------------MFRC522 register ---------------
#define         COMMAND_WAIT        0x02
#define         COMMAND_READBLOCK   0x03
#define         COMMAND_WRITEBLOCK  0x04
#define         MFRC522_HEADER      0xAB

#define         STATUS_ERROR        0
#define         STATUS_OK           1

#define         MIFARE_KEYA         0x00
#define         MIFARE_KEYB         0x01

/**
 * Constructor.
 */
MFRC522::MFRC522() {
}

/**
 * Description： Obtiene control del Serial para controlar MFRC522.
 * Ademas, pone MFRC522 en modo de espera.
 */
void MFRC522::begin(void) {
    uart_port_t uart_num = UART_NUM_2;
    uart_config_t uart_config = {
       .baud_rate = 9600,
       .data_bits = UART_DATA_8_BITS,
       .parity = UART_PARITY_DISABLE,
       .stop_bits = UART_STOP_BITS_1,
       .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
       .rx_flow_ctrl_thresh = 122,
    };
    //Set UART parameters
    uart_param_config(uart_num, &uart_config);
    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins,(-1: default pin, no change.)
    //For UART2, we can just use the default pins.
    uart_set_pin(uart_num, NFC_UART_TXD, NFC_UART_RXD, NFC_UART_RTS, NFC_UART_CTS);
    //Install UART driver, and get the queue.
    esp_err_t installed =  uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart2_queue, 0);
    printf("installed : %d\n", installed);
    wait();
}

/**
 * Description：Pone MFRC522 en modo espera.
 */
void MFRC522::wait() {
    write(COMMAND_WAIT);
}

/**
 * Description：Returns true if detect card in MFRC522.
 */
bool MFRC522::available() {
    return false;
}

/**
 * Description：Read the serial number of the card.
 */
void MFRC522::readCardSerial() {
    for (int i = 0; i < sizeof(cardSerial); ){
        if (available()){
            cardSerial[i] = read();
            i++;
        }
    }
}

/**
 * Description：Returns a pointer to array with card serial.
 */
byte *MFRC522::getCardSerial() {
    return cardSerial;
}

/**
 * Description：Read a block data of the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::getBlock(byte block, byte keyType, byte *key, byte *returnBlock) {
    byte sendData[8] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  // key
    };
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    return communicate(
        COMMAND_READBLOCK,  // command
        sendData,           // sendData
        0x0A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );
}

/**
 * Description：Write a block data in the card.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::writeBlock(byte block, byte keyType, byte *key, byte *data) {
    byte sendData[24] = {
        block,      // block
        keyType,    // key type
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // key
        0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Data
    };
    byte returnBlock[3];
    byte returnBlockLength;

    for (int i = 0; i < 6; ++i) {
        sendData[2 + i] = key[i];
    }

    for (int i = 0; i < 16; ++i) {
        sendData[8 + i] = data[i];
    }

    byte result = communicate(
        COMMAND_WRITEBLOCK, // command
        sendData,           // sendData
        0x1A,               // length
        returnBlock,        // returnData
        &returnBlockLength  // returnDataLength
    );

    return result;
}

/**
 * Description：Comunication between MFRC522 and ISO14443.
 * Return：Return STATUS_OK if success.
 */
bool MFRC522::communicate(byte command, byte *sendData, byte sendDataLength, byte *returnData, byte *returnDataLength) {
    // Send instruction to MFRC522
    write(MFRC522_HEADER);      // Header
    write(sendDataLength);      // Length (Length + Command + Data)
    write(command);             // Command

    for (int i = 0; i < sendDataLength - 2; i++) {
        write(sendData[i]);     // Data
    }

    // Read response to MFRC522
    while (!available());
    byte header = read();           // Header
    while (!available());
    *returnDataLength = read();     // Length (Length + Command + Data)
    while (!available());
    byte commandResult = read();    // Command result

    for (int i = 0; i < *returnDataLength - 2; i=i) {
        if (available()) {
            returnData[i] = read(); // Data
            i++;
        }
    }

    // Return
    if (command != commandResult) {
        return STATUS_ERROR;
    }

    return STATUS_OK;
}

/*
 * Description：Write a byte data into MFRC522.
 */
void MFRC522::write(byte value) {
    uart_port_t uart_num = UART_NUM_2;
    char data[1];
    data[0] = value;
    uart_write_bytes(uart_num, (const char*)data, 1);
}

/*
 * Description：Read a byte data of MFRC522
 * Return：Return the read value.
 */
byte MFRC522::read() {
    uart_port_t uart_num = UART_NUM_2;
    uint8_t *data = (uint8_t *)malloc(1);
    TickType_t ticks_to_wait = portTICK_RATE_MS;
    uart_read_bytes(uart_num,data,1,ticks_to_wait);
    return *data;
}

extern "C" void MFRC522_main() {
    MFRC522 Conector;
    Conector.begin();
    printf("begin :\n");
    //while(true)
    {
        //Conector.readCardSerial();
        printf("readCardSerial :\n");
        Conector.wait();
    }
}
<|endoftext|>


<commit_before>#include "types.h"
#include "amd64.h"
#include "kernel.hh"
#include "percpu.hh"
#include "wq.hh"
#include "cpputil.hh"
#include "ilist.hh"
#include "mtrace.h"

extern "C" void zpage(void*);
extern "C" void zrun_nc(void*);

static const bool prezero = true;

struct free_page
{
  ilink<free_page> link;
  typedef ilist<free_page, &free_page::link> list_t;
};

struct zallocator {
  // pages and nPages must only be accessed by the local CPU and must
  // be accessed with interrupts disabled.
  free_page::list_t pages;
  unsigned nPages;
  wframe frame;
};
percpu<zallocator> z_;

struct zwork : public work {
  zwork(wframe* frame)
    : frame_(frame)
  {
    frame_->inc();
  }

  virtual void run() {
    for (int i = 0; i < 32; i++) {
      auto *r = (struct free_page*)kalloc("zpage");
      if (r == nullptr)
        break;
      zrun_nc(r);
      scoped_cli cli;
      z_->pages.push_front(r);
      ++z_->nPages;
    }
    frame_->dec();
    delete this;
  }

  wframe* frame_;

  NEW_DELETE_OPS(zwork);
};

static void
tryrefill(void)
{
  int cpu = myid();
  if (prezero && z_[cpu].nPages < 16 && z_[cpu].frame.zero()) {
    zwork* w = new zwork(&z_[cpu].frame);
    if (wqcrit_push(w, cpu) < 0)
      delete w;
  }
}

// Allocate a zeroed page.  This page can be freed with kfree or, if
// it is known to be zeroed when it is freed, zfree.
char*
zalloc(const char* name)
{
  char* p = nullptr;

  {
    scoped_cli cli;
    if (!z_->pages.empty()) {
      p = (char*)&z_->pages.front();
      z_->pages.pop_front();
      --z_->nPages;
    }
  }

  if (p == nullptr) {
    p = kalloc(name);
    if (p != nullptr)
      zpage(p);
  } else {
    mtlabel(mtrace_label_block, p, PGSIZE, name, strlen(name));
    // Zero the free_page header
    memset(p, 0, sizeof(struct free_page));
    if (0)
      for (int i = 0; i < PGSIZE; i++)
        assert(p[i] == 0);
  }
  tryrefill();
  return p;
}

// Free a page that is known to be zero
void
zfree(void* p)
{
  if (0)
    for (int i = 0; i < 4096; i++)
      assert(((char*)p)[i] == 0);

  scoped_cli cli;
  z_->pages.push_front((struct free_page*)p);
  ++z_->nPages;
}

void
initz(void)
{
}
<commit_msg>mtrace fixes in zalloc<commit_after>#include "types.h"
#include "amd64.h"
#include "kernel.hh"
#include "percpu.hh"
#include "wq.hh"
#include "cpputil.hh"
#include "ilist.hh"
#include "mtrace.h"

extern "C" void zpage(void*);
extern "C" void zrun_nc(void*);

static const bool prezero = true;

struct free_page
{
  ilink<free_page> link;
  typedef ilist<free_page, &free_page::link> list_t;
};

struct zallocator {
  // pages and nPages must only be accessed by the local CPU and must
  // be accessed with interrupts disabled.
  free_page::list_t pages;
  unsigned nPages;
  wframe frame;
};
percpu<zallocator> z_;

struct zwork : public work {
  zwork(wframe* frame)
    : frame_(frame)
  {
    frame_->inc();
  }

  virtual void run() {
    for (int i = 0; i < 32; i++) {
      auto *r = (struct free_page*)kalloc("zpage");
      if (r == nullptr)
        break;
      zrun_nc(r);
      scoped_cli cli;
      z_->pages.push_front(r);
      ++z_->nPages;
    }
    frame_->dec();
    delete this;
  }

  wframe* frame_;

  NEW_DELETE_OPS(zwork);
};

static void
tryrefill(void)
{
  int cpu = myid();
  if (prezero && z_[cpu].nPages < 16 && z_[cpu].frame.zero()) {
    zwork* w = new zwork(&z_[cpu].frame);
    if (wqcrit_push(w, cpu) < 0)
      delete w;
  }
}

// Allocate a zeroed page.  This page can be freed with kfree or, if
// it is known to be zeroed when it is freed, zfree.
char*
zalloc(const char* name)
{
  char* p = nullptr;

  {
    scoped_cli cli;
    if (!z_->pages.empty()) {
      p = (char*)&z_->pages.front();
      z_->pages.pop_front();
      --z_->nPages;
    }
  }

  if (p == nullptr) {
    p = kalloc(name);
    if (p != nullptr)
      zpage(p);
  } else {
    mtunlabel(mtrace_label_block, p);
    mtlabel(mtrace_label_block, p, PGSIZE, name, strlen(name));
    // Zero the free_page header
    memset(p, 0, sizeof(struct free_page));
    if (0)
      for (int i = 0; i < PGSIZE; i++)
        assert(p[i] == 0);
  }
  tryrefill();
  return p;
}

// Free a page that is known to be zero
void
zfree(void* p)
{
  if (0)
    for (int i = 0; i < 4096; i++)
      assert(((char*)p)[i] == 0);

  scoped_cli cli;
  mtunlabel(mtrace_label_block, p);
  z_->pages.push_front((struct free_page*)p);
  ++z_->nPages;
}

void
initz(void)
{
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <iomanip>
#include <iostream>
#include "duration.h"
#include "function.h"
#include "function_statistics.h"
#include "performance_counter.h"
#include "statistics_writer_xml.h"
#include "statistics.h"
#include "time_utils.h"

namespace amx_profiler {

void StatisticsWriterXml::Write(const Statistics *stats)
{
	*stream() << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
	          << "<stats script=\"" << script_name() << "\"";

	if (print_date()) {
		*stream() << " timestamp=\"" << TimeStamp::Now() << "\"";
	}

	if (print_run_time()) {
		*stream() << " run_time=\"" << Seconds(stats->GetTotalRunTime()).count() << "\'";
	}

	*stream() << ">\n";

	std::vector<FunctionStatistics*> all_fn_stats;
	stats->GetStatistics(all_fn_stats);

	Nanoseconds time_all;
	for (std::vector<FunctionStatistics*>::const_iterator iterator = all_fn_stats.begin();
			iterator != all_fn_stats.end(); ++iterator)
	{
		const FunctionStatistics *fn_stats = *iterator;
		time_all += fn_stats->total_time() - fn_stats->child_time();
	}

	Nanoseconds total_time_all;
	for (std::vector<FunctionStatistics*>::const_iterator iterator = all_fn_stats.begin();
			iterator != all_fn_stats.end(); ++iterator)
	{
		const FunctionStatistics *fn_stats = *iterator;
		total_time_all += fn_stats->total_time();
	}

	for (std::vector<FunctionStatistics*>::const_iterator iterator = all_fn_stats.begin();
			iterator != all_fn_stats.end(); ++iterator)
	{
		const FunctionStatistics *fn_stats = *iterator;

		double self_time_sec = Seconds(fn_stats->GetSelfTime()).count();
		double self_time_percent = fn_stats->GetSelfTime().count() * 100 / time_all.count();

		double total_time_sec = Seconds(fn_stats->total_time()).count();
		double total_time_percent = fn_stats->total_time().count() * 100 / total_time_all.count();

		*stream() << "\t<function"
			<< " type=\"" << fn_stats->function()->GetTypeString() << "\""
			<< " name=\"" << fn_stats->function()->name() << "\""
			<< " calls=\"" << fn_stats->num_calls() << "\""
			<< " self_time=\"" << fn_stats->GetSelfTime().count() << "\""
			<< " self_time_sec=\"" << self_time_sec << "\""
			<< " self_time_percent=\"" <<  std::fixed << std::setprecision(2) << self_time_percent << "\""
			<< " total_time=\"" << fn_stats->total_time().count() << "\""
			<< " total_time_sec=\"" << total_time_sec << "\""
			<< " total_time_percent=\"" <<  std::fixed << std::setprecision(2) << total_time_percent << "\""
		<< "/>\n";
	}

	*stream() << "</stats>";
}

} // namespace amx_profiler

<commit_msg>Remove "self_time_sec" and "total_time_sec" attributes in XML output<commit_after>// Copyright (c) 2011-2013, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <iomanip>
#include <iostream>
#include "duration.h"
#include "function.h"
#include "function_statistics.h"
#include "performance_counter.h"
#include "statistics_writer_xml.h"
#include "statistics.h"
#include "time_utils.h"

namespace amx_profiler {

void StatisticsWriterXml::Write(const Statistics *stats)
{
	*stream() << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
	          << "<stats script=\"" << script_name() << "\"";

	if (print_date()) {
		*stream() << " timestamp=\"" << TimeStamp::Now() << "\"";
	}

	if (print_run_time()) {
		*stream() << " run_time=\"" << Seconds(stats->GetTotalRunTime()).count() << "\'";
	}

	*stream() << ">\n";

	std::vector<FunctionStatistics*> all_fn_stats;
	stats->GetStatistics(all_fn_stats);

	Nanoseconds time_all;
	for (std::vector<FunctionStatistics*>::const_iterator iterator = all_fn_stats.begin();
			iterator != all_fn_stats.end(); ++iterator)
	{
		const FunctionStatistics *fn_stats = *iterator;
		time_all += fn_stats->total_time() - fn_stats->child_time();
	}

	Nanoseconds total_time_all;
	for (std::vector<FunctionStatistics*>::const_iterator iterator = all_fn_stats.begin();
			iterator != all_fn_stats.end(); ++iterator)
	{
		const FunctionStatistics *fn_stats = *iterator;
		total_time_all += fn_stats->total_time();
	}

	for (std::vector<FunctionStatistics*>::const_iterator iterator = all_fn_stats.begin();
			iterator != all_fn_stats.end(); ++iterator)
	{
		const FunctionStatistics *fn_stats = *iterator;

		double self_time_percent = fn_stats->GetSelfTime().count() * 100 / time_all.count();
		double total_time_percent = fn_stats->total_time().count() * 100 / total_time_all.count();

		*stream() << "\t<function"
			<< " type=\"" << fn_stats->function()->GetTypeString() << "\""
			<< " name=\"" << fn_stats->function()->name() << "\""
			<< " calls=\"" << fn_stats->num_calls() << "\""
			<< " self_time=\"" << fn_stats->GetSelfTime().count() << "\""
			<< " self_time_percent=\"" <<  std::fixed << std::setprecision(2) << self_time_percent << "\""
			<< " total_time=\"" << fn_stats->total_time().count() << "\""
			<< " total_time_percent=\"" <<  std::fixed << std::setprecision(2) << total_time_percent << "\""
		<< "/>\n";
	}

	*stream() << "</stats>";
}

} // namespace amx_profiler

<|endoftext|>