<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../../mod/http-parser/http_parser.h"
#include <cctype>
#include <map>
#include <ostream>
#include <uri>

namespace uri {

///////////////////////////////////////////////////////////////////////////////
static inline bool icase_equal(const std::experimental::string_view lhs, const std::experimental::string_view rhs) noexcept {
  return (lhs.size() == rhs.size())
         and
         std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), [](const char a, const char b) {
          return std::tolower(a) == std::tolower(b);
         });
}

///////////////////////////////////////////////////////////////////////////////
static inline uint16_t bind_port(const std::experimental::string_view scheme,
                                 const uint16_t port_from_uri) noexcept
{
  static const std::initializer_list<std::pair<const std::experimental::string_view, uint16_t>> scheme_port_mapping
  {
    {"ftp",    21U},  {"FTP",    21U},
    {"http",   80U},  {"HTTP",   80U},
    {"https",  443U}, {"HTTPS",  443U},
    {"irc",    6667U},{"IRC",    6667U},
    {"ldap",   389U}, {"LDAP",   389U},
    {"nntp",   119U}, {"NNTP",   119U},
    {"rtsp",   554U}, {"RTSP",   554U},
    {"sip",    5060U},{"SIP",    5060U},
    {"sips",   5061U},{"SIPS",   5061U},
    {"smtp",   25U},  {"SMTP",   25U},
    {"ssh",    22U},  {"SSH",    22U},
    {"telnet", 23U},  {"TELNET", 23U},
    {"ws",     80U},  {"WS",     80U},
    {"xmpp",   5222U},{"XMPP",   5222U}
  };
  static const std::map<std::experimental::string_view, uint16_t> port_table
  {scheme_port_mapping};

  if (port_from_uri not_eq 0) return port_from_uri;

  const auto it = port_table.find(scheme);
  // Slow case insensitive compare
  /*
  const auto it = std::find_if(port_table.begin(), port_table.end(),
    [scheme] (const std::pair<std::experimental::string_view, uint16_t>& pair)
    {
      return icase_equal(pair.first, scheme);
    });
  */
  return (it not_eq port_table.cend()) ? it->second : 0xFFFFU;
}

///////////////////////////////////////////////////////////////////////////////
// copy helper
///////////////////////////////////////////////////////////////////////////////
static inline std::experimental::string_view updated_copy(const std::string& to_copy,
                                                          const std::experimental::string_view& view,
                                                          const std::string& from_copy)
{
  return {to_copy.data() + (view.data() - from_copy.data()), view.size()};
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(const char* uri, const bool parse)
  : uri_str_{decode(uri)}
{
  if (parse) this->parse();
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(const std::experimental::string_view uri, const bool parse)
  : uri_str_{decode(uri)}
{
  if (parse) this->parse();
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(const URI& u)
  : uri_str_  {u.uri_str_}
  , port_     {u.port_}
  , scheme_   {updated_copy(uri_str_, u.scheme_,   u.uri_str_)}
  , userinfo_ {updated_copy(uri_str_, u.userinfo_, u.uri_str_)}
  , host_     {updated_copy(uri_str_, u.host_,     u.uri_str_)}
  , port_str_ {updated_copy(uri_str_, u.port_str_, u.uri_str_)}
  , path_     {updated_copy(uri_str_, u.path_,     u.uri_str_)}
  , query_    {updated_copy(uri_str_, u.query_,    u.uri_str_)}
  , fragment_ {updated_copy(uri_str_, u.fragment_, u.uri_str_)}
  , query_map_{}
{
  for(const auto& ent : u.query_map_)
  {
    query_map_.emplace(updated_copy(uri_str_, ent.first,  u.uri_str_),
                       updated_copy(uri_str_, ent.second, u.uri_str_));
  }
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(URI&& u) noexcept
  : uri_str_{std::move(u.uri_str_)}
  , port_     {u.port_}
  , scheme_   {u.scheme_}
  , userinfo_ {u.userinfo_}
  , host_     {u.host_}
  , port_str_ {u.port_str_}
  , path_     {u.path_}
  , query_    {u.query_}
  , fragment_ {u.fragment_}
  , query_map_{std::move(u.query_map_)}
{}

///////////////////////////////////////////////////////////////////////////////
URI& URI::operator=(const URI& u) {
  uri_str_  = u.uri_str_;
  port_     = u.port_;
  scheme_   = updated_copy(uri_str_, u.scheme_,   u.uri_str_);
  userinfo_ = updated_copy(uri_str_, u.userinfo_, u.uri_str_);
  host_     = updated_copy(uri_str_, u.host_,     u.uri_str_);
  port_str_ = updated_copy(uri_str_, u.port_str_, u.uri_str_);
  path_     = updated_copy(uri_str_, u.path_,     u.uri_str_);
  query_    = updated_copy(uri_str_, u.query_,    u.uri_str_);
  fragment_ = updated_copy(uri_str_, u.fragment_, u.uri_str_);

  query_map_.clear();

  for(const auto& ent : u.query_map_) {
    query_map_.emplace(updated_copy(uri_str_, ent.first,  u.uri_str_),
                       updated_copy(uri_str_, ent.second, u.uri_str_));
  }

  return *this;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::operator=(URI&& u) noexcept {
  uri_str_   = std::move(u.uri_str_);
  port_      = u.port_;
  scheme_    = u.scheme_;
  userinfo_  = u.userinfo_;
  host_      = u.host_;
  port_str_  = u.port_str_;
  path_      = u.path_;
  query_     = u.query_;
  fragment_  = u.fragment_;
  query_map_ = std::move(u.query_map_);

  return *this;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::scheme() const noexcept {
  return scheme_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::userinfo() const noexcept {
  return userinfo_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::host() const noexcept {
  return host_;
}

///////////////////////////////////////////////////////////////////////////////
bool URI::host_is_ip4() const noexcept {
  return host_.empty() ? false : std::isdigit(host_.back());
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::host_and_port() const noexcept {
  if (not port_str_.empty()) {
    return std::experimental::string_view{host_.data(), host_.length() + port_str_.length() + 1};
  } else {
    return host_;
  }
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::port_str() const noexcept {
  return port_str_;
}

///////////////////////////////////////////////////////////////////////////////
uint16_t URI::port() const noexcept {
  return port_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::path() const noexcept {
  return path_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::query() const noexcept {
  return query_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::fragment() const noexcept {
  return fragment_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::query(const std::experimental::string_view key) {
  if (query_map_.empty() and (not query_.empty())) {
    load_queries();
  }

  const auto target = query_map_.find(key);

  return (target not_eq query_map_.cend()) ? target->second : std::experimental::string_view{};
}

///////////////////////////////////////////////////////////////////////////////
bool URI::is_valid() const noexcept {
  return (not host_.empty()) or (not path_.empty()) ;
}

///////////////////////////////////////////////////////////////////////////////
URI::operator bool() const noexcept {
  return is_valid();
}

///////////////////////////////////////////////////////////////////////////////
const std::string& URI::to_string() const noexcept {
  return uri_str_;
}

///////////////////////////////////////////////////////////////////////////////
URI::operator std::string () const {
  return uri_str_;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::operator << (const std::string& chunk) {
  uri_str_.append(chunk);
  return *this;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::parse() {
  http_parser_url u;
  http_parser_url_init(&u);

  const auto p = uri_str_.data();
  const auto result = http_parser_parse_url(p, uri_str_.length(), 0, &u);

#ifdef URI_THROW_ON_ERROR
  if (result not_eq 0) {
    throw URI_error{"Invalid uri: " + uri_str_};
  }
#endif //< URI_THROW_ON_ERROR

  (void)result;

  using sview = std::experimental::string_view;

  scheme_   = (u.field_set & (1 << UF_SCHEMA))   ? sview{p + u.field_data[UF_SCHEMA].off,   u.field_data[UF_SCHEMA].len}   : sview{};
  userinfo_ = (u.field_set & (1 << UF_USERINFO)) ? sview{p + u.field_data[UF_USERINFO].off, u.field_data[UF_USERINFO].len} : sview{};
  host_     = (u.field_set & (1 << UF_HOST))     ? sview{p + u.field_data[UF_HOST].off,     u.field_data[UF_HOST].len}     : sview{};
  port_str_ = (u.field_set & (1 << UF_PORT))     ? sview{p + u.field_data[UF_PORT].off,     u.field_data[UF_PORT].len}     : sview{};
  path_     = (u.field_set & (1 << UF_PATH))     ? sview{p + u.field_data[UF_PATH].off,     u.field_data[UF_PATH].len}     : sview{};
  query_    = (u.field_set & (1 << UF_QUERY))    ? sview{p + u.field_data[UF_QUERY].off,    u.field_data[UF_QUERY].len}    : sview{};
  fragment_ = (u.field_set & (1 << UF_FRAGMENT)) ? sview{p + u.field_data[UF_FRAGMENT].off, u.field_data[UF_FRAGMENT].len} : sview{};

  port_ = bind_port(scheme_, u.port);

  return *this;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::reset() {
  new (this) URI{};
  return *this;
}

///////////////////////////////////////////////////////////////////////////////
void URI::load_queries() {
  auto _ = query_;

  std::experimental::string_view name  {};
  std::experimental::string_view value {};
  std::experimental::string_view::size_type base {0U};
  std::experimental::string_view::size_type break_point {};

  while (true) {
    if ((break_point = _.find('=')) not_eq std::experimental::string_view::npos) {
      name = _.substr(base, break_point);
      //-----------------------------------
      _.remove_prefix(name.length() + 1U);
    }
    else {
      break;
    }

    if ((break_point = _.find('&')) not_eq std::experimental::string_view::npos) {
      value = _.substr(base, break_point);
      query_map_.emplace(name, value);
      _.remove_prefix(value.length() + 1U);
    }
    else {
      query_map_.emplace(name, _);
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
bool operator < (const URI& lhs, const URI& rhs) noexcept {
  return lhs.to_string() < rhs.to_string();
}

///////////////////////////////////////////////////////////////////////////////
bool operator == (const URI& lhs, const URI& rhs) noexcept {
  return icase_equal(lhs.scheme(), rhs.scheme())
         and (lhs.userinfo() == rhs.userinfo())
         and icase_equal(lhs.host(), rhs.host())
         and lhs.port() == rhs.port()
         and lhs.path() == rhs.path()
         and lhs.query() == rhs.query()
         and lhs.fragment() == rhs.fragment();
}

///////////////////////////////////////////////////////////////////////////////
std::ostream& operator<< (std::ostream& output_device, const URI& uri) {
  return output_device << uri.to_string();
}

} //< namespace uri
<commit_msg>util: Refactored bind_port function in URI module<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>
#include <cctype>
#include <ostream>
#include <uri>
#include <utility>
#include <vector>

#include "../../mod/http-parser/http_parser.h"

namespace uri {

///////////////////////////////////////////////////////////////////////////////
static inline bool icase_equal(const std::experimental::string_view lhs, const std::experimental::string_view rhs) noexcept {
  return (lhs.size() == rhs.size())
         and
         std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), [](const char a, const char b) {
          return std::tolower(a) == std::tolower(b);
         });
}

///////////////////////////////////////////////////////////////////////////////
static inline uint16_t bind_port(const std::experimental::string_view scheme,
                                 const uint16_t port_from_uri) noexcept
{
  static const std::vector<std::pair<const std::experimental::string_view, uint16_t>> port_table
  {
    {"ftp",    21U},
    {"http",   80U},
    {"https",  443U},
    {"irc",    6667U},
    {"ldap",   389U},
    {"nntp",   119U},
    {"rtsp",   554U},
    {"sip",    5060U},
    {"sips",   5061U},
    {"smtp",   25U},
    {"ssh",    22U},
    {"telnet", 23U},
    {"ws",     80U},
    {"xmpp",   5222U},
  };

  if (port_from_uri not_eq 0) return port_from_uri;

  const auto it = std::find_if(port_table.cbegin(), port_table.cend(), [scheme](const auto& _) {
      return icase_equal(_.first, scheme);
  });

  return (it not_eq port_table.cend()) ? it->second : 0xFFFFU;
}

///////////////////////////////////////////////////////////////////////////////
// copy helper
///////////////////////////////////////////////////////////////////////////////
static inline std::experimental::string_view updated_copy(const std::string& to_copy,
                                                          const std::experimental::string_view& view,
                                                          const std::string& from_copy)
{
  return {to_copy.data() + (view.data() - from_copy.data()), view.size()};
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(const char* uri, const bool parse)
  : uri_str_{decode(uri)}
{
  if (parse) this->parse();
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(const std::experimental::string_view uri, const bool parse)
  : uri_str_{decode(uri)}
{
  if (parse) this->parse();
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(const URI& u)
  : uri_str_  {u.uri_str_}
  , port_     {u.port_}
  , scheme_   {updated_copy(uri_str_, u.scheme_,   u.uri_str_)}
  , userinfo_ {updated_copy(uri_str_, u.userinfo_, u.uri_str_)}
  , host_     {updated_copy(uri_str_, u.host_,     u.uri_str_)}
  , port_str_ {updated_copy(uri_str_, u.port_str_, u.uri_str_)}
  , path_     {updated_copy(uri_str_, u.path_,     u.uri_str_)}
  , query_    {updated_copy(uri_str_, u.query_,    u.uri_str_)}
  , fragment_ {updated_copy(uri_str_, u.fragment_, u.uri_str_)}
  , query_map_{}
{
  for(const auto& ent : u.query_map_)
  {
    query_map_.emplace(updated_copy(uri_str_, ent.first,  u.uri_str_),
                       updated_copy(uri_str_, ent.second, u.uri_str_));
  }
}

///////////////////////////////////////////////////////////////////////////////
URI::URI(URI&& u) noexcept
  : uri_str_{std::move(u.uri_str_)}
  , port_     {u.port_}
  , scheme_   {u.scheme_}
  , userinfo_ {u.userinfo_}
  , host_     {u.host_}
  , port_str_ {u.port_str_}
  , path_     {u.path_}
  , query_    {u.query_}
  , fragment_ {u.fragment_}
  , query_map_{std::move(u.query_map_)}
{}

///////////////////////////////////////////////////////////////////////////////
URI& URI::operator=(const URI& u) {
  uri_str_  = u.uri_str_;
  port_     = u.port_;
  scheme_   = updated_copy(uri_str_, u.scheme_,   u.uri_str_);
  userinfo_ = updated_copy(uri_str_, u.userinfo_, u.uri_str_);
  host_     = updated_copy(uri_str_, u.host_,     u.uri_str_);
  port_str_ = updated_copy(uri_str_, u.port_str_, u.uri_str_);
  path_     = updated_copy(uri_str_, u.path_,     u.uri_str_);
  query_    = updated_copy(uri_str_, u.query_,    u.uri_str_);
  fragment_ = updated_copy(uri_str_, u.fragment_, u.uri_str_);

  query_map_.clear();

  for(const auto& ent : u.query_map_) {
    query_map_.emplace(updated_copy(uri_str_, ent.first,  u.uri_str_),
                       updated_copy(uri_str_, ent.second, u.uri_str_));
  }

  return *this;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::operator=(URI&& u) noexcept {
  uri_str_   = std::move(u.uri_str_);
  port_      = u.port_;
  scheme_    = u.scheme_;
  userinfo_  = u.userinfo_;
  host_      = u.host_;
  port_str_  = u.port_str_;
  path_      = u.path_;
  query_     = u.query_;
  fragment_  = u.fragment_;
  query_map_ = std::move(u.query_map_);

  return *this;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::scheme() const noexcept {
  return scheme_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::userinfo() const noexcept {
  return userinfo_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::host() const noexcept {
  return host_;
}

///////////////////////////////////////////////////////////////////////////////
bool URI::host_is_ip4() const noexcept {
  return host_.empty() ? false : std::isdigit(host_.back());
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::host_and_port() const noexcept {
  if (not port_str_.empty()) {
    return std::experimental::string_view{host_.data(), host_.length() + port_str_.length() + 1};
  } else {
    return host_;
  }
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::port_str() const noexcept {
  return port_str_;
}

///////////////////////////////////////////////////////////////////////////////
uint16_t URI::port() const noexcept {
  return port_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::path() const noexcept {
  return path_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::query() const noexcept {
  return query_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::fragment() const noexcept {
  return fragment_;
}

///////////////////////////////////////////////////////////////////////////////
std::experimental::string_view URI::query(const std::experimental::string_view key) {
  if (query_map_.empty() and (not query_.empty())) {
    load_queries();
  }

  const auto target = query_map_.find(key);

  return (target not_eq query_map_.cend()) ? target->second : std::experimental::string_view{};
}

///////////////////////////////////////////////////////////////////////////////
bool URI::is_valid() const noexcept {
  return (not host_.empty()) or (not path_.empty()) ;
}

///////////////////////////////////////////////////////////////////////////////
URI::operator bool() const noexcept {
  return is_valid();
}

///////////////////////////////////////////////////////////////////////////////
const std::string& URI::to_string() const noexcept {
  return uri_str_;
}

///////////////////////////////////////////////////////////////////////////////
URI::operator std::string () const {
  return uri_str_;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::operator << (const std::string& chunk) {
  uri_str_.append(chunk);
  return *this;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::parse() {
  http_parser_url u;
  http_parser_url_init(&u);

  const auto p = uri_str_.data();
  const auto result = http_parser_parse_url(p, uri_str_.length(), 0, &u);

#ifdef URI_THROW_ON_ERROR
  if (result not_eq 0) {
    throw URI_error{"Invalid uri: " + uri_str_};
  }
#endif //< URI_THROW_ON_ERROR

  (void)result;

  using sview = std::experimental::string_view;

  scheme_   = (u.field_set & (1 << UF_SCHEMA))   ? sview{p + u.field_data[UF_SCHEMA].off,   u.field_data[UF_SCHEMA].len}   : sview{};
  userinfo_ = (u.field_set & (1 << UF_USERINFO)) ? sview{p + u.field_data[UF_USERINFO].off, u.field_data[UF_USERINFO].len} : sview{};
  host_     = (u.field_set & (1 << UF_HOST))     ? sview{p + u.field_data[UF_HOST].off,     u.field_data[UF_HOST].len}     : sview{};
  port_str_ = (u.field_set & (1 << UF_PORT))     ? sview{p + u.field_data[UF_PORT].off,     u.field_data[UF_PORT].len}     : sview{};
  path_     = (u.field_set & (1 << UF_PATH))     ? sview{p + u.field_data[UF_PATH].off,     u.field_data[UF_PATH].len}     : sview{};
  query_    = (u.field_set & (1 << UF_QUERY))    ? sview{p + u.field_data[UF_QUERY].off,    u.field_data[UF_QUERY].len}    : sview{};
  fragment_ = (u.field_set & (1 << UF_FRAGMENT)) ? sview{p + u.field_data[UF_FRAGMENT].off, u.field_data[UF_FRAGMENT].len} : sview{};

  port_ = bind_port(scheme_, u.port);

  return *this;
}

///////////////////////////////////////////////////////////////////////////////
URI& URI::reset() {
  new (this) URI{};
  return *this;
}

///////////////////////////////////////////////////////////////////////////////
void URI::load_queries() {
  auto _ = query_;

  std::experimental::string_view name  {};
  std::experimental::string_view value {};
  std::experimental::string_view::size_type base {0U};
  std::experimental::string_view::size_type break_point {};

  while (true) {
    if ((break_point = _.find('=')) not_eq std::experimental::string_view::npos) {
      name = _.substr(base, break_point);
      //-----------------------------------
      _.remove_prefix(name.length() + 1U);
    }
    else {
      break;
    }

    if ((break_point = _.find('&')) not_eq std::experimental::string_view::npos) {
      value = _.substr(base, break_point);
      query_map_.emplace(name, value);
      _.remove_prefix(value.length() + 1U);
    }
    else {
      query_map_.emplace(name, _);
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
bool operator < (const URI& lhs, const URI& rhs) noexcept {
  return lhs.to_string() < rhs.to_string();
}

///////////////////////////////////////////////////////////////////////////////
bool operator == (const URI& lhs, const URI& rhs) noexcept {
  return icase_equal(lhs.scheme(), rhs.scheme())
         and (lhs.userinfo() == rhs.userinfo())
         and icase_equal(lhs.host(), rhs.host())
         and lhs.port() == rhs.port()
         and lhs.path() == rhs.path()
         and lhs.query() == rhs.query()
         and lhs.fragment() == rhs.fragment();
}

///////////////////////////////////////////////////////////////////////////////
std::ostream& operator<< (std::ostream& output_device, const URI& uri) {
  return output_device << uri.to_string();
}

} //< namespace uri
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: edimp.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 17:14:25 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _EDIMP_HXX
#define _EDIMP_HXX

#include "crsrsh.hxx"
#include "doc.hxx"
#include "viscrs.hxx"

/*
 * MACROS um ueber alle Bereiche zu iterieren
 */
#define PCURCRSR (_pStartCrsr)

#define FOREACHPAM_START(pCURSH) \
    {\
        SwPaM *_pStartCrsr = (pCURSH)->GetCrsr(), *__pStartCrsr = _pStartCrsr; \
        do {

#define FOREACHPAM_END() \
        } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr ); \
    }

#define FOREACHCURSOR_START(pCURSH) \
    {\
        SwShellCrsr *_pStartCrsr = *(pCURSH)->GetSwCrsr(), *__pStartCrsr = _pStartCrsr; \
        do {

#define FOREACHCURSOR_END() \
        } while( (_pStartCrsr=*(SwCursor*)_pStartCrsr->GetNext()) != __pStartCrsr ); \
    }

struct SwPamRange
{
    ULONG nStart, nEnd;

    SwPamRange() : nStart( 0 ), nEnd( 0 )   {}
    SwPamRange( ULONG nS, ULONG nE ) : nStart( nS ), nEnd( nE ) {}

    BOOL operator==( const SwPamRange& rRg )
        { return nStart == rRg.nStart ? TRUE : FALSE; }
    BOOL operator<( const SwPamRange& rRg )
        { return nStart < rRg.nStart ? TRUE : FALSE; }
};

SV_DECL_VARARR_SORT( _SwPamRanges, SwPamRange, 0, 1 )

class SwPamRanges : private _SwPamRanges
{
public:
    SwPamRanges( const SwPaM& rRing );

    void Insert( const SwNodeIndex& rIdx1, const SwNodeIndex& rIdx2 );
    SwPaM& SetPam( USHORT nArrPos, SwPaM& rPam );

    USHORT Count() const
                {   return _SwPamRanges::Count(); }
    SwPamRange operator[]( USHORT nPos ) const
                { return _SwPamRanges::operator[](nPos); }
};

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.1.1.1.1462); FILE MERGED 2005/09/05 13:35:55 rt 1.1.1.1.1462.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: edimp.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:43:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _EDIMP_HXX
#define _EDIMP_HXX

#include "crsrsh.hxx"
#include "doc.hxx"
#include "viscrs.hxx"

/*
 * MACROS um ueber alle Bereiche zu iterieren
 */
#define PCURCRSR (_pStartCrsr)

#define FOREACHPAM_START(pCURSH) \
    {\
        SwPaM *_pStartCrsr = (pCURSH)->GetCrsr(), *__pStartCrsr = _pStartCrsr; \
        do {

#define FOREACHPAM_END() \
        } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr ); \
    }

#define FOREACHCURSOR_START(pCURSH) \
    {\
        SwShellCrsr *_pStartCrsr = *(pCURSH)->GetSwCrsr(), *__pStartCrsr = _pStartCrsr; \
        do {

#define FOREACHCURSOR_END() \
        } while( (_pStartCrsr=*(SwCursor*)_pStartCrsr->GetNext()) != __pStartCrsr ); \
    }

struct SwPamRange
{
    ULONG nStart, nEnd;

    SwPamRange() : nStart( 0 ), nEnd( 0 )   {}
    SwPamRange( ULONG nS, ULONG nE ) : nStart( nS ), nEnd( nE ) {}

    BOOL operator==( const SwPamRange& rRg )
        { return nStart == rRg.nStart ? TRUE : FALSE; }
    BOOL operator<( const SwPamRange& rRg )
        { return nStart < rRg.nStart ? TRUE : FALSE; }
};

SV_DECL_VARARR_SORT( _SwPamRanges, SwPamRange, 0, 1 )

class SwPamRanges : private _SwPamRanges
{
public:
    SwPamRanges( const SwPaM& rRing );

    void Insert( const SwNodeIndex& rIdx1, const SwNodeIndex& rIdx2 );
    SwPaM& SetPam( USHORT nArrPos, SwPaM& rPam );

    USHORT Count() const
                {   return _SwPamRanges::Count(); }
    SwPamRange operator[]( USHORT nPos ) const
                { return _SwPamRanges::operator[](nPos); }
};

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ndgrf.hxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: hr $ $Date: 2003-07-16 18:07:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _NDGRF_HXX
#define _NDGRF_HXX

#ifndef _LNKBASE_HXX //autogen
#include <so3/lnkbase.hxx>
#endif
#ifndef _GRFMGR_HXX //autogen
#include <goodies/grfmgr.hxx>
#endif
#ifndef _NDNOTXT_HXX
#include <ndnotxt.hxx>
#endif

class SwGrfFmtColl;
class SwDoc;
class GraphicAttr;
class SvStorage;

// --------------------
// SwGrfNode
// --------------------
class SwGrfNode: public SwNoTxtNode
{
    friend class SwNodes;
    friend class SwGrfFrm;

    GraphicObject aGrfObj;
    ::so3::SvBaseLinkRef refLink;       // falls Grafik nur als Link, dann Pointer gesetzt
    Size nGrfSize;
//  String aStrmName;           // SW3: Name des Storage-Streams fuer Embedded
    String aNewStrmName;        // SW3/XML: new stream name (either SW3 stream
                                // name or package url)
    String aLowResGrf;          // HTML: LowRes Grafik (Ersatzdarstellung bis
                                //      die normale (HighRes) geladen ist.

    BOOL bTransparentFlagValid  :1;
    BOOL bInSwapIn              :1;
    BOOL bGrafikArrived         :1;
    BOOL bChgTwipSize           :1;
    BOOL bChgTwipSizeFromPixel  :1;
    BOOL bLoadLowResGrf         :1;
    BOOL bFrameInPaint          :1; //Um Start-/EndActions im Paint (ueber
                                    //SwapIn zu verhindern.
    BOOL bScaleImageMap         :1; //Image-Map in SetTwipSize skalieren

    SwGrfNode( const SwNodeIndex& rWhere,
               const String& rGrfName, const String& rFltName,
               const Graphic* pGraphic,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    // Ctor fuer Einlesen (SW/G) ohne Grafik
    SwGrfNode( const SwNodeIndex& rWhere,
               const String& rGrfName, const String& rFltName,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    SwGrfNode( const SwNodeIndex& rWhere,
               const GraphicObject& rGrfObj,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );

    void InsertLink( const String& rGrfName, const String& rFltName );
    BOOL ImportGraphic( SvStream& rStrm );
    BOOL HasStreamName() const { return aGrfObj.HasUserData(); }
    BOOL GetStreamStorageNames( String& rStrmName, String& rStgName ) const;
    void DelStreamName();

    DECL_LINK( SwapGraphic, GraphicObject* );

public:
    virtual ~SwGrfNode();

    const Graphic&          GetGrf() const      { return aGrfObj.GetGraphic(); }
    const GraphicObject&    GetGrfObj() const   { return aGrfObj; }
          GraphicObject&    GetGrfObj()         { return aGrfObj; }

    virtual SwCntntNode *SplitNode( const SwPosition & );

    virtual Size GetTwipSize() const;
#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
    void SetTwipSize( const Size& rSz );

    BOOL IsTransparent() const;

    inline BOOL IsAnimated() const              { return aGrfObj.IsAnimated(); }

    inline BOOL IsChgTwipSize() const           { return bChgTwipSize; }
    inline BOOL IsChgTwipSizeFromPixel() const  { return bChgTwipSizeFromPixel; }
    inline void SetChgTwipSize( BOOL b, BOOL bFromPx=FALSE )        { bChgTwipSize = b; bChgTwipSizeFromPixel = bFromPx; }

    inline BOOL IsGrafikArrived() const         { return bGrafikArrived; }
    inline void SetGrafikArrived( BOOL b )      { bGrafikArrived = b; }

    inline BOOL IsFrameInPaint() const          { return bFrameInPaint; }
    inline void SetFrameInPaint( BOOL b )       { bFrameInPaint = b; }

    inline BOOL IsScaleImageMap() const         { return bScaleImageMap; }
    inline void SetScaleImageMap( BOOL b )      { bScaleImageMap = b; }

    // alles fuers Laden der LowRes-Grafiken
    inline BOOL IsLoadLowResGrf() const         { return bLoadLowResGrf; }
    inline void SetLoadLowResGrf( BOOL b )      { bLoadLowResGrf = b; }
    const String& GetLowResGrfName() const      { return aLowResGrf; }
    void SetLowResGrfName( const String& r )    { aLowResGrf = r; }
#endif
        // steht in ndcopy.cxx
    virtual SwCntntNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const;
#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
        // erneutes Einlesen, falls Graphic nicht Ok ist. Die
        // aktuelle wird durch die neue ersetzt.
    BOOL ReRead( const String& rGrfName, const String& rFltName,
                  const Graphic* pGraphic = 0,
                  const GraphicObject* pGrfObj = 0,
                  BOOL bModify = TRUE );
        // Laden der Grafik unmittelbar vor der Anzeige
    short SwapIn( BOOL bWaitForData = FALSE );
        // Entfernen der Grafik, um Speicher freizugeben
    short SwapOut();
        // Schreiben der Grafik
    BOOL StoreGraphics( SvStorage* pDocStg = NULL );
        // Zugriff auf den Storage-Streamnamen
    String GetStreamName() const;
    void SetStreamName( const String& r ) { aGrfObj.SetUserData( r ); }
    void SetNewStreamName( const String& r ) { aNewStrmName = r; }
    void SaveCompleted( BOOL bClear );
    // is this node selected by any shell?
    BOOL IsSelected() const;
#endif

        // Der Grafik sagen, dass sich der Node im Undobereich befindet
    virtual BOOL SavePersistentData();
    virtual BOOL RestorePersistentData();

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
        // Abfrage der Link-Daten
    BOOL IsGrfLink() const                  { return refLink.Is(); }
    inline BOOL IsLinkedFile() const;
    inline BOOL IsLinkedDDE() const;
    ::so3::SvBaseLinkRef GetLink() const    { return refLink; }
    BOOL GetFileFilterNms( String* pFileNm, String* pFilterNm ) const;
    void ReleaseLink();

        // Prioritaet beim Laden der Grafik setzen. Geht nur, wenn der Link
        // ein FileObject gesetzt hat
    void SetTransferPriority( USHORT nPrio );

    // Skalieren einer Image-Map: Die Image-Map wird um den Faktor
    // zwischen Grafik-Groesse und Rahmen-Groesse vergroessert/verkleinert
    void ScaleImageMap();

    // returns the with our graphic attributes filled Graphic-Attr-Structure
    GraphicAttr& GetGraphicAttr( GraphicAttr&, const SwFrm* pFrm ) const;

#endif
};

// ----------------------------------------------------------------------
// Inline Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
#if !(defined(MACOSX) && ( __GNUC__ < 3 ))
// GrP moved to gcc_outl.cxx; revisit with gcc3
inline       SwGrfNode   *SwNode::GetGrfNode()
{
     return ND_GRFNODE == nNodeType ? (SwGrfNode*)this : 0;
}
inline const SwGrfNode   *SwNode::GetGrfNode() const
{
     return ND_GRFNODE == nNodeType ? (const SwGrfNode*)this : 0;
}
#endif

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
inline BOOL SwGrfNode::IsLinkedFile() const
{
    return refLink.Is() && OBJECT_CLIENT_GRF == refLink->GetObjType();
}
inline BOOL SwGrfNode::IsLinkedDDE() const
{
    return refLink.Is() && OBJECT_CLIENT_DDE == refLink->GetObjType();
}
#endif

#endif
<commit_msg>INTEGRATION: CWS geordi2q14 (1.11.274); FILE MERGED 2004/01/30 14:26:17 hr 1.11.274.1: #111934#: merge CWS ooo111fix2<commit_after>/*************************************************************************
 *
 *  $RCSfile: ndgrf.hxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-02 18:02:30 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _NDGRF_HXX
#define _NDGRF_HXX

#ifndef _LNKBASE_HXX //autogen
#include <so3/lnkbase.hxx>
#endif
#ifndef _GRFMGR_HXX //autogen
#include <goodies/grfmgr.hxx>
#endif
#ifndef _NDNOTXT_HXX
#include <ndnotxt.hxx>
#endif

class SwGrfFmtColl;
class SwDoc;
class GraphicAttr;
class SvStorage;

// --------------------
// SwGrfNode
// --------------------
class SwGrfNode: public SwNoTxtNode
{
    friend class SwNodes;
    friend class SwGrfFrm;

    GraphicObject aGrfObj;
    ::so3::SvBaseLinkRef refLink;       // falls Grafik nur als Link, dann Pointer gesetzt
    Size nGrfSize;
//  String aStrmName;           // SW3: Name des Storage-Streams fuer Embedded
    String aNewStrmName;        // SW3/XML: new stream name (either SW3 stream
                                // name or package url)
    String aLowResGrf;          // HTML: LowRes Grafik (Ersatzdarstellung bis
                                //      die normale (HighRes) geladen ist.

    BOOL bTransparentFlagValid  :1;
    BOOL bInSwapIn              :1;
    BOOL bGrafikArrived         :1;
    BOOL bChgTwipSize           :1;
    BOOL bChgTwipSizeFromPixel  :1;
    BOOL bLoadLowResGrf         :1;
    BOOL bFrameInPaint          :1; //Um Start-/EndActions im Paint (ueber
                                    //SwapIn zu verhindern.
    BOOL bScaleImageMap         :1; //Image-Map in SetTwipSize skalieren

    SwGrfNode( const SwNodeIndex& rWhere,
               const String& rGrfName, const String& rFltName,
               const Graphic* pGraphic,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    // Ctor fuer Einlesen (SW/G) ohne Grafik
    SwGrfNode( const SwNodeIndex& rWhere,
               const String& rGrfName, const String& rFltName,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    SwGrfNode( const SwNodeIndex& rWhere,
               const GraphicObject& rGrfObj,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );

    void InsertLink( const String& rGrfName, const String& rFltName );
    BOOL ImportGraphic( SvStream& rStrm );
    BOOL HasStreamName() const { return aGrfObj.HasUserData(); }
    BOOL GetStreamStorageNames( String& rStrmName, String& rStgName ) const;
    void DelStreamName();

    DECL_LINK( SwapGraphic, GraphicObject* );

public:
    virtual ~SwGrfNode();

    const Graphic&          GetGrf() const      { return aGrfObj.GetGraphic(); }
    const GraphicObject&    GetGrfObj() const   { return aGrfObj; }
          GraphicObject&    GetGrfObj()         { return aGrfObj; }

    virtual SwCntntNode *SplitNode( const SwPosition & );

    virtual Size GetTwipSize() const;
#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
    void SetTwipSize( const Size& rSz );

    BOOL IsTransparent() const;

    inline BOOL IsAnimated() const              { return aGrfObj.IsAnimated(); }

    inline BOOL IsChgTwipSize() const           { return bChgTwipSize; }
    inline BOOL IsChgTwipSizeFromPixel() const  { return bChgTwipSizeFromPixel; }
    inline void SetChgTwipSize( BOOL b, BOOL bFromPx=FALSE )        { bChgTwipSize = b; bChgTwipSizeFromPixel = bFromPx; }

    inline BOOL IsGrafikArrived() const         { return bGrafikArrived; }
    inline void SetGrafikArrived( BOOL b )      { bGrafikArrived = b; }

    inline BOOL IsFrameInPaint() const          { return bFrameInPaint; }
    inline void SetFrameInPaint( BOOL b )       { bFrameInPaint = b; }

    inline BOOL IsScaleImageMap() const         { return bScaleImageMap; }
    inline void SetScaleImageMap( BOOL b )      { bScaleImageMap = b; }

    // alles fuers Laden der LowRes-Grafiken
    inline BOOL IsLoadLowResGrf() const         { return bLoadLowResGrf; }
    inline void SetLoadLowResGrf( BOOL b )      { bLoadLowResGrf = b; }
    const String& GetLowResGrfName() const      { return aLowResGrf; }
    void SetLowResGrfName( const String& r )    { aLowResGrf = r; }
#endif
        // steht in ndcopy.cxx
    virtual SwCntntNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const;
#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
        // erneutes Einlesen, falls Graphic nicht Ok ist. Die
        // aktuelle wird durch die neue ersetzt.
    BOOL ReRead( const String& rGrfName, const String& rFltName,
                  const Graphic* pGraphic = 0,
                  const GraphicObject* pGrfObj = 0,
                  BOOL bModify = TRUE );
        // Laden der Grafik unmittelbar vor der Anzeige
    short SwapIn( BOOL bWaitForData = FALSE );
        // Entfernen der Grafik, um Speicher freizugeben
    short SwapOut();
        // Schreiben der Grafik
    BOOL StoreGraphics( SvStorage* pDocStg = NULL );
        // Zugriff auf den Storage-Streamnamen
    String GetStreamName() const;
    void SetStreamName( const String& r ) { aGrfObj.SetUserData( r ); }
    void SetNewStreamName( const String& r ) { aNewStrmName = r; }
    void SaveCompleted( BOOL bClear );
    // is this node selected by any shell?
    BOOL IsSelected() const;
#endif

        // Der Grafik sagen, dass sich der Node im Undobereich befindet
    virtual BOOL SavePersistentData();
    virtual BOOL RestorePersistentData();

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
        // Abfrage der Link-Daten
    BOOL IsGrfLink() const                  { return refLink.Is(); }
    inline BOOL IsLinkedFile() const;
    inline BOOL IsLinkedDDE() const;
    ::so3::SvBaseLinkRef GetLink() const    { return refLink; }
    BOOL GetFileFilterNms( String* pFileNm, String* pFilterNm ) const;
    void ReleaseLink();

        // Prioritaet beim Laden der Grafik setzen. Geht nur, wenn der Link
        // ein FileObject gesetzt hat
    void SetTransferPriority( USHORT nPrio );

    // Skalieren einer Image-Map: Die Image-Map wird um den Faktor
    // zwischen Grafik-Groesse und Rahmen-Groesse vergroessert/verkleinert
    void ScaleImageMap();

    // returns the with our graphic attributes filled Graphic-Attr-Structure
    GraphicAttr& GetGraphicAttr( GraphicAttr&, const SwFrm* pFrm ) const;

#endif
};

// ----------------------------------------------------------------------
// Inline Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
inline       SwGrfNode   *SwNode::GetGrfNode()
{
     return ND_GRFNODE == nNodeType ? (SwGrfNode*)this : 0;
}
inline const SwGrfNode   *SwNode::GetGrfNode() const
{
     return ND_GRFNODE == nNodeType ? (const SwGrfNode*)this : 0;
}

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
inline BOOL SwGrfNode::IsLinkedFile() const
{
    return refLink.Is() && OBJECT_CLIENT_GRF == refLink->GetObjType();
}
inline BOOL SwGrfNode::IsLinkedDDE() const
{
    return refLink.Is() && OBJECT_CLIENT_DDE == refLink->GetObjType();
}
#endif

#endif
<|endoftext|>


<commit_before>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include "tryto.h"

#include <unordered_map>

#include <boost/io/detail/quoted_manip.hpp>

namespace osquery {

namespace impl {

Expected<bool, ConversionError> stringToBool(std::string from) {
 static const auto table = std::unordered_map<std::string, bool>{
     {"1", true},
     {"0", false},
     {"y", true},
     {"yes", true},
     {"n", false},
     {"no", false},
     {"t", true},
     {"true", true},
     {"f", false},
     {"false", false},
     {"ok", true},
     {"disable", false},
     {"enable", true},
 };
 using CharType = std::string::value_type;
 // Classic locale could be used here because all available string
 // representations of boolean have ascii encoding. It must be a bit faster.
 static const auto& ctype =
     std::use_facet<std::ctype<CharType>>(std::locale::classic());
 for (auto& ch : from) {
   ch = ctype.tolower(ch);
 }
 const auto it = table.find(from);
 if (it == table.end()) {
   return createError(ConversionError::InvalidArgument)
          << "Wrong string representation of boolean "
          << boost::io::quoted(from);
 }
 return it->second;
}

} // namespace impl

} // namespace osquery
<commit_msg>[shell] support previously supported on|off toggle for osqueryi shell functions (#5876)<commit_after>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include "tryto.h"

#include <unordered_map>

#include <boost/io/detail/quoted_manip.hpp>

namespace osquery {

namespace impl {

Expected<bool, ConversionError> stringToBool(std::string from) {
  static const auto table = std::unordered_map<std::string, bool>{
      {"1", true},
      {"0", false},
      {"y", true},
      {"yes", true},
      {"n", false},
      {"no", false},
      {"t", true},
      {"true", true},
      {"f", false},
      {"false", false},
      {"ok", true},
      {"disable", false},
      {"enable", true},
      {"on", true},
      {"off", false},
  };
  using CharType = std::string::value_type;
  // Classic locale could be used here because all available string
  // representations of boolean have ascii encoding. It must be a bit faster.
  static const auto& ctype =
      std::use_facet<std::ctype<CharType>>(std::locale::classic());
  for (auto& ch : from) {
    ch = ctype.tolower(ch);
  }
  const auto it = table.find(from);
  if (it == table.end()) {
    return createError(ConversionError::InvalidArgument)
           << "Wrong string representation of boolean "
           << boost::io::quoted(from);
  }
  return it->second;
}

} // namespace impl

} // namespace osquery
<|endoftext|>


<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "RhodesApp.h"
#include "common/RhoMutexLock.h"
#include "common/IRhoClassFactory.h"
#include "common/RhoFile.h"
#include "common/RhoConf.h"
#include "common/RhoFilePath.h"
#include "common/Tokenizer.h"

using namespace rho;
using namespace rho::common;
extern "C" void rho_sys_app_exit();
extern "C" void rho_sys_impl_show_errormessage(const char* szTitle, const char* szMsg);

#if !defined(OS_WINDOWS) && !defined(OS_WINCE)
void rho_sys_impl_show_errormessage(const char* szTitle, const char* szMsg)
{
}
#endif

namespace rho {
namespace common {

class CFileTransaction
{
    unsigned int m_nError;
    String m_strError;
    String m_strFolder;
public:
    CFileTransaction(const String& strFolder);
    ~CFileTransaction();
    unsigned int start();
    void commit();
    unsigned int rollback();

    boolean isError(){ return m_nError != 0; }
    unsigned int getError(){ return m_nError; }
    String getErrorText(){ return m_strError; }

};

class CReplaceBundleThread : public rho::common::CRhoThread
{
    DEFINE_LOGCLASS;

    String m_bundle_path;

    unsigned int removeFilesByList( const String& strListPath, const String& strSrcFolder );
    unsigned int moveFilesByList( const String& strListPath, const String& strSrcFolder, const String& strDstFolder );
    void doReplaceBundle();
public:

    CReplaceBundleThread(const char* root_path)
    {
        m_bundle_path = root_path;
        start(rho::common::IRhoRunnable::epNormal);
    }

    virtual ~CReplaceBundleThread() {}

    virtual void run();

    static void showError(int nError, const String& strError );
};
IMPLEMENT_LOGCLASS(CReplaceBundleThread,"RhoBundle");

CFileTransaction::CFileTransaction(const String& strFolder) : m_strFolder(strFolder)
{
}

unsigned int CFileTransaction::start()
{
    //CRhoFile::createFolder((m_strFolder + "_temp_journal").c_str());

    m_nError = CRhoFile::copyFoldersContentToAnotherFolder( CFilePath::join(m_strFolder, "").c_str(), (m_strFolder + "_temp_journal").c_str() );
    if (m_nError)
    {
        m_strError = "Unable to copy folder: " + m_strFolder + " to : " + m_strFolder + "_temp_journal";
        return m_nError;
    }

    m_nError = CRhoFile::renameFile( (m_strFolder + "_temp_journal").c_str(), (m_strFolder + "_journal").c_str());
    if (m_nError)
    {
        m_strError = "Unable to rename folder: " + m_strFolder + "_temp_journal to : " + m_strFolder + "_journal";
        return m_nError;
    }

    return m_nError;
}

CFileTransaction::~CFileTransaction()
{
    rollback();
}

void CFileTransaction::commit()
{
    String strFolder = m_strFolder;

    m_nError = CRhoFile::renameFile( (strFolder + "_journal").c_str(), (strFolder + "_temp_journal").c_str() );
    if (m_nError)
    {
        m_strError = "Unable to rename folder: " + strFolder + "_journal to : " + strFolder + "_temp_journal";
        return;
    }
    m_strFolder = "";

    m_nError = CRhoFile::deleteFolder( (strFolder + "_temp_journal").c_str() );
    if (m_nError)
    {
        m_strError = "Unable to delete folder: " + strFolder + "_temp_journal";
        return;
    }

}

unsigned int CFileTransaction::rollback()
{
    String strFolder = m_strFolder;
    m_strFolder = "";

    if ( strFolder.length() == 0 )
        return 0;

    CRhoFile::deleteFolder( CFilePath(strFolder).changeBaseName("RhoBundle").c_str() );
    CRhoFile::deleteFolder( (strFolder + "_temp_journal").c_str() );

    if ( !CRhoFile::isFileExist((strFolder + "_journal").c_str()) )
        return 0;

    m_nError = CRhoFile::deleteFolder( (strFolder).c_str() );
    if (m_nError)
    {
        m_strError = "Unable to delete folder: " + strFolder;
        CReplaceBundleThread::showError(m_nError, m_strError);
        return m_nError;
    }

    m_nError = CRhoFile::renameFile( (strFolder + "_journal").c_str(), (strFolder).c_str() );
    if (m_nError)
    {
        m_strError = "Unable to rename folder: " + strFolder + "_journal" + " to : " + strFolder;
        CReplaceBundleThread::showError(m_nError, m_strError);
        return m_nError;
    }

    return m_nError;
}

unsigned int CReplaceBundleThread::removeFilesByList( const String& strListPath, const String& strSrcFolder )
{
    unsigned int nError = 0;
    String strList;
    CRhoFile::loadTextFile(strListPath.c_str(), strList);

    CTokenizer oTokenizer( strList, "\n" );
	while (oTokenizer.hasMoreTokens())
    {
		String strLine = oTokenizer.nextToken();

        CTokenizer oLineTok( strLine, "\t" );
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strPath = oLineTok.nextToken();
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strType = oLineTok.nextToken();

        if ( strType.compare("file") == 0)
        {
            nError = CRhoFile::deleteFile( CFilePath::join( strSrcFolder,strPath).c_str() );
            if (nError != 0)
            {
                LOG(ERROR) + "Cannot remove file: " + CFilePath::join( strSrcFolder,strPath);
                break;
            }
        }
    }

    return nError;
}

unsigned int CReplaceBundleThread::moveFilesByList( const String& strListPath, const String& strSrcFolder, const String& strDestFolder )
{
    unsigned int nError = 0;
    String strList;
    CRhoFile::loadTextFile(strListPath.c_str(), strList);

    CTokenizer oTokenizer( strList, "\n" );
	while (oTokenizer.hasMoreTokens())
    {
		String strLine = oTokenizer.nextToken();

        CTokenizer oLineTok( strLine, "\t" );
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strPath = oLineTok.nextToken();
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strType = oLineTok.nextToken();
        String strSrcPath = CFilePath::join( strSrcFolder,strPath);
        String strDstPath = CFilePath::join( strDestFolder, strPath );

        if ( strType.compare("dir") == 0)
        {
            CRhoFile::createFolder(strDstPath.c_str());
        }else if ( strType.compare("file") == 0)
        {
            nError = CRhoFile::renameFile( strSrcPath.c_str(), strDstPath.c_str() );
            if (nError != 0)
            {
                LOG(ERROR) + "Cannot rename file from : " + strSrcPath + "; to: " + strDstPath;
                break;
            }
        }
    }

    return nError;
}

void CReplaceBundleThread::showError(int nError, const String& strError )
{
    LOG(ERROR) + "Error happen when replace bundle: " + strError + "; Code: " + LOGFMT("%d") + nError;

    String strMsg = "Error happen when replace bundle: " + strError;

    rho_sys_impl_show_errormessage("Bundle update", strMsg.c_str());
}

void CReplaceBundleThread::run()
{
    //Stop application
    rho_rhodesapp_callAppActiveCallback(0);
    rho_rhodesapp_callUiDestroyedCallback();
    RHODESAPP().stopApp();

    doReplaceBundle();

    rho_platform_restart_application();
    rho_sys_app_exit();
}

void CReplaceBundleThread::doReplaceBundle()
{
    CFileTransaction oFT( RHODESAPP().getAppRootPath());
    if (oFT.start())
    {
        showError(oFT.getError(), oFT.getErrorText());
        return;
    }

    //Remove current files
    unsigned int nError = removeFilesByList( CFilePath::join( RHODESAPP().getAppRootPath(), "rhofilelist.txt"), ::RHODESAPP().getAppRootPath() );
    if ( nError != 0 )
    {
        showError(nError, "Remove files from bundle failed." );
        return;
    }

    LOG(INFO) + "START";
    //Copy new bundle
    //nError = CRhoFile::moveFoldersContentToAnotherFolder( CFilePath::join(m_bundle_path, "RhoBundle/apps").c_str(), ::RHODESAPP().getAppRootPath().c_str() );
    nError = moveFilesByList( CFilePath::join(m_bundle_path, "RhoBundle/apps/rhofilelist.txt").c_str(), CFilePath::join(m_bundle_path, "RhoBundle/apps"), ::RHODESAPP().getAppRootPath().c_str() );
    if ( nError != 0 )
    {
        showError(nError, "Copy files to bundle failed." );
        return;
    }
    LOG(INFO) + "STOP";
    oFT.commit();

    //Delete bundle folder
    CRhoFile::deleteFolder( m_bundle_path.c_str());
}

}
}

extern "C"
{

void rho_sys_replace_current_bundle(const char* path)
{
    new CReplaceBundleThread(path);
}

int rho_sys_check_rollback_bundle(const char* szRhoPath)
{
    CFileTransaction oFT( CFilePath::join(szRhoPath, "apps") );
    return oFT.rollback() != 0 ? 0 : 1;
}

int rho_sys_delete_folder(const char* szRhoPath)
{
    return CRhoFile::deleteFolder(szRhoPath);
}

} //extern "C"

<commit_msg>iphone: fix bundle manager<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "RhodesApp.h"
#include "common/RhoMutexLock.h"
#include "common/IRhoClassFactory.h"
#include "common/RhoFile.h"
#include "common/RhoConf.h"
#include "common/RhoFilePath.h"
#include "common/Tokenizer.h"

using namespace rho;
using namespace rho::common;
extern "C" void rho_sys_app_exit();
extern "C" void rho_sys_impl_show_errormessage(const char* szTitle, const char* szMsg);

#if !defined(OS_WINDOWS) && !defined(OS_WINCE)
void rho_sys_impl_show_errormessage(const char* szTitle, const char* szMsg)
{
}
#endif

namespace rho {
namespace common {

class CFileTransaction
{
    unsigned int m_nError;
    String m_strError;
    String m_strFolder;
public:
    CFileTransaction(const String& strFolder);
    ~CFileTransaction();
    unsigned int start();
    void commit();
    unsigned int rollback();

    boolean isError(){ return m_nError != 0; }
    unsigned int getError(){ return m_nError; }
    String getErrorText(){ return m_strError; }

};

class CReplaceBundleThread : public rho::common::CRhoThread
{
    DEFINE_LOGCLASS;

    String m_bundle_path;

    unsigned int removeFilesByList( const String& strListPath, const String& strSrcFolder );
    unsigned int moveFilesByList( const String& strListPath, const String& strSrcFolder, const String& strDstFolder );
    void doReplaceBundle();
public:

    CReplaceBundleThread(const char* root_path)
    {
        m_bundle_path = root_path;
        start(rho::common::IRhoRunnable::epNormal);
    }

    virtual ~CReplaceBundleThread() {}

    virtual void run();

    static void showError(int nError, const String& strError );
};
IMPLEMENT_LOGCLASS(CReplaceBundleThread,"RhoBundle");

CFileTransaction::CFileTransaction(const String& strFolder) : m_strFolder(strFolder)
{
}

unsigned int CFileTransaction::start()
{
    CRhoFile::createFolder((m_strFolder + "_temp_journal").c_str());

    m_nError = CRhoFile::copyFoldersContentToAnotherFolder( CFilePath::join(m_strFolder, "").c_str(), (m_strFolder + "_temp_journal").c_str() );
    if (m_nError)
    {
        m_strError = "Unable to copy folder: " + m_strFolder + " to : " + m_strFolder + "_temp_journal";
        return m_nError;
    }

    m_nError = CRhoFile::renameFile( (m_strFolder + "_temp_journal").c_str(), (m_strFolder + "_journal").c_str());
    if (m_nError)
    {
        m_strError = "Unable to rename folder: " + m_strFolder + "_temp_journal to : " + m_strFolder + "_journal";
        return m_nError;
    }

    return m_nError;
}

CFileTransaction::~CFileTransaction()
{
    rollback();
}

void CFileTransaction::commit()
{
    String strFolder = m_strFolder;

    m_nError = CRhoFile::renameFile( (strFolder + "_journal").c_str(), (strFolder + "_temp_journal").c_str() );
    if (m_nError)
    {
        m_strError = "Unable to rename folder: " + strFolder + "_journal to : " + strFolder + "_temp_journal";
        return;
    }
    m_strFolder = "";

    m_nError = CRhoFile::deleteFolder( (strFolder + "_temp_journal").c_str() );
    if (m_nError)
    {
        m_strError = "Unable to delete folder: " + strFolder + "_temp_journal";
        return;
    }

}

unsigned int CFileTransaction::rollback()
{
    String strFolder = m_strFolder;
    m_strFolder = "";

    if ( strFolder.length() == 0 )
        return 0;

    CRhoFile::deleteFolder( CFilePath(strFolder).changeBaseName("RhoBundle").c_str() );
    CRhoFile::deleteFolder( (strFolder + "_temp_journal").c_str() );

    if ( !CRhoFile::isFileExist((strFolder + "_journal").c_str()) )
        return 0;

    m_nError = CRhoFile::deleteFolder( (strFolder).c_str() );
    if (m_nError)
    {
        m_strError = "Unable to delete folder: " + strFolder;
        CReplaceBundleThread::showError(m_nError, m_strError);
        return m_nError;
    }

    m_nError = CRhoFile::renameFile( (strFolder + "_journal").c_str(), (strFolder).c_str() );
    if (m_nError)
    {
        m_strError = "Unable to rename folder: " + strFolder + "_journal" + " to : " + strFolder;
        CReplaceBundleThread::showError(m_nError, m_strError);
        return m_nError;
    }

    return m_nError;
}

unsigned int CReplaceBundleThread::removeFilesByList( const String& strListPath, const String& strSrcFolder )
{
    unsigned int nError = 0;
    String strList;
    CRhoFile::loadTextFile(strListPath.c_str(), strList);

    CTokenizer oTokenizer( strList, "\n" );
	while (oTokenizer.hasMoreTokens())
    {
		String strLine = oTokenizer.nextToken();

        CTokenizer oLineTok( strLine, "\t" );
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strPath = oLineTok.nextToken();
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strType = oLineTok.nextToken();

        if ( strType.compare("file") == 0)
        {
            nError = CRhoFile::deleteFile( CFilePath::join( strSrcFolder,strPath).c_str() );
            if (nError != 0)
            {
                LOG(ERROR) + "Cannot remove file: " + CFilePath::join( strSrcFolder,strPath);
                break;
            }
        }
    }

    return nError;
}

unsigned int CReplaceBundleThread::moveFilesByList( const String& strListPath, const String& strSrcFolder, const String& strDestFolder )
{
    unsigned int nError = 0;
    String strList;
    CRhoFile::loadTextFile(strListPath.c_str(), strList);

    CTokenizer oTokenizer( strList, "\n" );
	while (oTokenizer.hasMoreTokens())
    {
		String strLine = oTokenizer.nextToken();

        CTokenizer oLineTok( strLine, "\t" );
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strPath = oLineTok.nextToken();
        if ( !oLineTok.hasMoreTokens() )
            continue;
        String strType = oLineTok.nextToken();
        String strSrcPath = CFilePath::join( strSrcFolder,strPath);
        String strDstPath = CFilePath::join( strDestFolder, strPath );

        if ( strType.compare("dir") == 0)
        {
            CRhoFile::createFolder(strDstPath.c_str());
        }else if ( strType.compare("file") == 0)
        {
            nError = CRhoFile::renameFile( strSrcPath.c_str(), strDstPath.c_str() );
            if (nError != 0)
            {
                LOG(ERROR) + "Cannot rename file from : " + strSrcPath + "; to: " + strDstPath;
                break;
            }
        }
    }

    return nError;
}

void CReplaceBundleThread::showError(int nError, const String& strError )
{
    LOG(ERROR) + "Error happen when replace bundle: " + strError + "; Code: " + LOGFMT("%d") + nError;

    String strMsg = "Error happen when replace bundle: " + strError;

    rho_sys_impl_show_errormessage("Bundle update", strMsg.c_str());
}

void CReplaceBundleThread::run()
{
    //Stop application
    rho_rhodesapp_callAppActiveCallback(0);
    rho_rhodesapp_callUiDestroyedCallback();
    RHODESAPP().stopApp();

    doReplaceBundle();

    rho_platform_restart_application();
    rho_sys_app_exit();
}

void CReplaceBundleThread::doReplaceBundle()
{
    CFileTransaction oFT( RHODESAPP().getAppRootPath());
    if (oFT.start())
    {
        showError(oFT.getError(), oFT.getErrorText());
        return;
    }

    //Remove current files
    unsigned int nError = removeFilesByList( CFilePath::join( RHODESAPP().getAppRootPath(), "rhofilelist.txt"), ::RHODESAPP().getAppRootPath() );
    if ( nError != 0 )
    {
        showError(nError, "Remove files from bundle failed." );
        return;
    }

    LOG(INFO) + "START";
    //Copy new bundle
    //nError = CRhoFile::moveFoldersContentToAnotherFolder( CFilePath::join(m_bundle_path, "RhoBundle/apps").c_str(), ::RHODESAPP().getAppRootPath().c_str() );
    nError = moveFilesByList( CFilePath::join(m_bundle_path, "RhoBundle/apps/rhofilelist.txt").c_str(), CFilePath::join(m_bundle_path, "RhoBundle/apps"), ::RHODESAPP().getAppRootPath().c_str() );
    if ( nError != 0 )
    {
        showError(nError, "Copy files to bundle failed." );
        return;
    }
    LOG(INFO) + "STOP";
    oFT.commit();

    //Delete bundle folder
    CRhoFile::deleteFolder( m_bundle_path.c_str());
}

}
}

extern "C"
{

void rho_sys_replace_current_bundle(const char* path)
{
    new CReplaceBundleThread(path);
}

int rho_sys_check_rollback_bundle(const char* szRhoPath)
{
    CFileTransaction oFT( CFilePath::join(szRhoPath, "apps") );
    return oFT.rollback() != 0 ? 0 : 1;
}

int rho_sys_delete_folder(const char* szRhoPath)
{
    return CRhoFile::deleteFolder(szRhoPath);
}

} //extern "C"

<|endoftext|>


<commit_before>/*===================================================

	DIALOG MASTER CODE

===================================================*/

// Global Include
#include <blackbox/plugin/bb.h>
#include <commdlg.h>

//Includes
#include "PluginMaster.h"
#include "Definitions.h"

//Define these variables
wchar_t *dialog_filename;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//dialog_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int dialog_startup()
{
	dialog_filename = new wchar_t[MAX_PATH];
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//dialog_shutdown
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int dialog_shutdown()
{
	delete dialog_filename;
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//dialog_openfile
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wchar_t *dialog_file(const wchar_t *filter, const wchar_t *title, const wchar_t *defaultpath, const wchar_t *defaultextension, bool save)
{
	OPENFILENAME ofn;       // common dialog box structure

	// Initialize OPENFILENAME
	ZeroMemory(&ofn, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = NULL;
	ofn.lpstrFile = dialog_filename;
	//
	// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
	// use the contents of szFile to initialize itself.
	//
	ofn.lpstrFile[0] = '\0';
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFilter = filter;
	ofn.nFilterIndex = 1;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.lpstrInitialDir = defaultpath;
	ofn.lpstrTitle = title;
	ofn.lpstrDefExt = defaultextension;

	// Display the Open dialog box.

	if (save)
	{
		ofn.Flags = OFN_PATHMUSTEXIST;
		if (GetSaveFileName(&ofn)) return dialog_filename;
	}
	else
	{
		ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS;
		if (GetOpenFileName(&ofn)) return dialog_filename;
	}

	return 0;
}

/*=================================================*/

<commit_msg>* delete[] is a right counterpart for new[]<commit_after>/*===================================================

	DIALOG MASTER CODE

===================================================*/

// Global Include
#include <blackbox/plugin/bb.h>
#include <commdlg.h>

//Includes
#include "PluginMaster.h"
#include "Definitions.h"

//Define these variables
wchar_t *dialog_filename;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//dialog_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int dialog_startup()
{
	dialog_filename = new wchar_t[MAX_PATH];
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//dialog_shutdown
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int dialog_shutdown()
{
	delete[] dialog_filename;
	dialog_filename = nullptr;
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//dialog_openfile
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wchar_t *dialog_file(const wchar_t *filter, const wchar_t *title, const wchar_t *defaultpath, const wchar_t *defaultextension, bool save)
{
	OPENFILENAME ofn;       // common dialog box structure

	// Initialize OPENFILENAME
	ZeroMemory(&ofn, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = NULL;
	ofn.lpstrFile = dialog_filename;
	//
	// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
	// use the contents of szFile to initialize itself.
	//
	ofn.lpstrFile[0] = '\0';
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFilter = filter;
	ofn.nFilterIndex = 1;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.lpstrInitialDir = defaultpath;
	ofn.lpstrTitle = title;
	ofn.lpstrDefExt = defaultextension;

	// Display the Open dialog box.

	if (save)
	{
		ofn.Flags = OFN_PATHMUSTEXIST;
		if (GetSaveFileName(&ofn)) return dialog_filename;
	}
	else
	{
		ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS;
		if (GetOpenFileName(&ofn)) return dialog_filename;
	}

	return 0;
}

/*=================================================*/

<|endoftext|>


<commit_before>#include "xchainer/backprop.h"

#include <vector>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA
#include <gtest/gtest.h>

#include "xchainer/array.h"
#include "xchainer/backprop.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/dtype.h"
#include "xchainer/shape.h"

namespace xchainer {
namespace {

std::vector<Array> MakeFullArrays(const Shape& shape, const std::vector<float>& values, bool requires_grad) {
    std::vector<Array> ret;
    for (float value : values) {
        ret.push_back(Array::Full(shape, value));
        ret.back().set_requires_grad(requires_grad);
    }
    return ret;
}

class BackpropTest : public ::testing::TestWithParam<::testing::tuple<std::string>> {
protected:
    virtual void SetUp() {
        std::string device_name = ::testing::get<0>(GetParam());
        device_scope_ = std::make_unique<DeviceScope>(device_name);
    }

    virtual void TearDown() { device_scope_.reset(); }

public:
    template <typename T>
    void ExpectEqual(const Array& expected, const Array& actual) const {
        EXPECT_EQ(expected.dtype(), actual.dtype());
        EXPECT_EQ(expected.shape(), actual.shape());
        ExpectDataEqual<T>(expected, actual);
    }

    template <typename T>
    void ExpectDataEqual(const Array& expected, const Array& actual) const {
#ifdef XCHAINER_ENABLE_CUDA
        std::string device_name = ::testing::get<0>(GetParam());
        if (device_name == "cuda") {
            cuda::CheckError(cudaDeviceSynchronize());
        }
#endif  // XCHAINER_ENABLE_CUDA
        auto total_size = expected.shape().total_size();
        const T* expected_data = static_cast<const T*>(expected.data().get());
        const T* actual_data = static_cast<const T*>(actual.data().get());
        for (decltype(total_size) i = 0; i < total_size; i++) {
            EXPECT_EQ(expected_data[i], actual_data[i]);
        }
    }

    // Checks the correctness of Backward() applied to the output of a given function.
    // Gradients are only computed w.r.t. target_inputs, and are compared to expected_grads.
    template <typename Fprop>
    void CheckBackprop(std::vector<Array>& target_inputs, std::vector<Array>& other_inputs, std::vector<Array>& expected_grads,
                       Fprop&& fprop) const {
        EXPECT_EQ(expected_grads.size(), target_inputs.size());
        auto y = fprop(target_inputs, other_inputs);
        Backward(y);
        for (size_t i = 0; i < expected_grads.size(); ++i) {
            ExpectEqual<float>(expected_grads[i], *target_inputs[i].grad());
        }
    }

    // Simple version. It makes and uses an array with one element for each input.
    template <typename Fprop>
    void CheckBackprop(std::vector<float> target_inputs, std::vector<float> other_inputs, std::vector<float> expected_grads,
                       Fprop&& fprop) const {
        auto xs = MakeFullArrays({1}, target_inputs, true);
        auto other_xs = MakeFullArrays({1}, other_inputs, false);
        auto expected_gxs = MakeFullArrays({1}, expected_grads, false);
        CheckBackprop(xs, other_xs, expected_gxs, std::forward<Fprop>(fprop));
    }

private:
    std::unique_ptr<DeviceScope> device_scope_;
};

TEST_P(BackpropTest, Backward) {
    CheckBackprop({2.0f}, {3.0f}, {7.0f}, [](auto& xs, auto& ys) { return xs[0] * (xs[0] + ys[0]); });
}

TEST_P(BackpropTest, BackwardNoGrad) {
    auto x = Array::Full({1}, 2.0f);
    auto y = Array::Full({1}, 3.0f);
    auto z = x * y;
    Backward(z);
    EXPECT_FALSE(x.grad());
    EXPECT_FALSE(y.grad());
}

TEST_P(BackpropTest, DoubleBackprop) {
    auto fprop = [](auto& xs, auto& ys) {
        auto z = xs[0] * (xs[0] + ys[0]);
        Backward(z);
        auto gx = *xs[0].grad();
        xs[0].ClearGrad();
        return gx;
    };
    CheckBackprop({2.0f}, {3.0f}, {2.0f}, fprop);
}

TEST_P(BackpropTest, BackwardIdenticalInputs) {
    CheckBackprop({2.0f}, {}, {2.0f}, [](auto& xs, __attribute__((unused)) auto& ys) { return xs[0] + xs[0]; });
}

TEST_P(BackpropTest, InputGradient) {
    auto fprop = [](auto& xs, __attribute__((unused)) auto& ys) {
        xs[0].set_grad(Array::OnesLike(xs[0]));
        return xs[0];
    };
    CheckBackprop({1.0f}, {}, {2.0f}, fprop);
}

TEST_P(BackpropTest, OutputGradient) {
    auto x = Array::Ones({1}, TypeToDtype<float>);
    x.set_requires_grad(true);
    auto y = x;
    y.set_grad(Array::FullLike(y, 2.0f));
    Backward(y);
    auto e = Array::FullLike(x, 2.0f);
    ExpectEqual<float>(e, *x.grad());
}

INSTANTIATE_TEST_CASE_P(ForEachDevice, BackpropTest, ::testing::Values(
#ifdef XCHAINER_ENABLE_CUDA
                                                         std::string{"cuda"},
#endif  // XCHAINER_ENABLE_CUDA
                                                         std::string{"cpu"}));

}  // namespace
}  // namespace xchainer
<commit_msg>Fix test names<commit_after>#include "xchainer/backprop.h"

#include <vector>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA
#include <gtest/gtest.h>

#include "xchainer/array.h"
#include "xchainer/backprop.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/dtype.h"
#include "xchainer/shape.h"

namespace xchainer {
namespace {

std::vector<Array> MakeFullArrays(const Shape& shape, const std::vector<float>& values, bool requires_grad) {
    std::vector<Array> ret;
    for (float value : values) {
        ret.push_back(Array::Full(shape, value));
        ret.back().set_requires_grad(requires_grad);
    }
    return ret;
}

class BackpropTest : public ::testing::TestWithParam<::testing::tuple<std::string>> {
protected:
    virtual void SetUp() {
        std::string device_name = ::testing::get<0>(GetParam());
        device_scope_ = std::make_unique<DeviceScope>(device_name);
    }

    virtual void TearDown() { device_scope_.reset(); }

public:
    template <typename T>
    void ExpectEqual(const Array& expected, const Array& actual) const {
        EXPECT_EQ(expected.dtype(), actual.dtype());
        EXPECT_EQ(expected.shape(), actual.shape());
        ExpectDataEqual<T>(expected, actual);
    }

    template <typename T>
    void ExpectDataEqual(const Array& expected, const Array& actual) const {
#ifdef XCHAINER_ENABLE_CUDA
        std::string device_name = ::testing::get<0>(GetParam());
        if (device_name == "cuda") {
            cuda::CheckError(cudaDeviceSynchronize());
        }
#endif  // XCHAINER_ENABLE_CUDA
        auto total_size = expected.shape().total_size();
        const T* expected_data = static_cast<const T*>(expected.data().get());
        const T* actual_data = static_cast<const T*>(actual.data().get());
        for (decltype(total_size) i = 0; i < total_size; i++) {
            EXPECT_EQ(expected_data[i], actual_data[i]);
        }
    }

    // Checks the correctness of Backward() applied to the output of a given function.
    // Gradients are only computed w.r.t. target_inputs, and are compared to expected_grads.
    template <typename Fprop>
    void CheckBackprop(std::vector<Array>& target_inputs, std::vector<Array>& other_inputs, std::vector<Array>& expected_grads,
                       Fprop&& fprop) const {
        EXPECT_EQ(expected_grads.size(), target_inputs.size());
        auto y = fprop(target_inputs, other_inputs);
        Backward(y);
        for (size_t i = 0; i < expected_grads.size(); ++i) {
            ExpectEqual<float>(expected_grads[i], *target_inputs[i].grad());
        }
    }

    // Simple version. It makes and uses an array with one element for each input.
    template <typename Fprop>
    void CheckBackprop(std::vector<float> target_inputs, std::vector<float> other_inputs, std::vector<float> expected_grads,
                       Fprop&& fprop) const {
        auto xs = MakeFullArrays({1}, target_inputs, true);
        auto other_xs = MakeFullArrays({1}, other_inputs, false);
        auto expected_gxs = MakeFullArrays({1}, expected_grads, false);
        CheckBackprop(xs, other_xs, expected_gxs, std::forward<Fprop>(fprop));
    }

private:
    std::unique_ptr<DeviceScope> device_scope_;
};

TEST_P(BackpropTest, Backward) {
    CheckBackprop({2.0f}, {3.0f}, {7.0f}, [](auto& xs, auto& ys) { return xs[0] * (xs[0] + ys[0]); });
}

TEST_P(BackpropTest, BackwardNoGrad) {
    auto x = Array::Full({1}, 2.0f);
    auto y = Array::Full({1}, 3.0f);
    auto z = x * y;
    Backward(z);
    EXPECT_FALSE(x.grad());
    EXPECT_FALSE(y.grad());
}

TEST_P(BackpropTest, DoubleBackprop) {
    auto fprop = [](auto& xs, auto& ys) {
        auto z = xs[0] * (xs[0] + ys[0]);
        Backward(z);
        auto gx = *xs[0].grad();
        xs[0].ClearGrad();
        return gx;
    };
    CheckBackprop({2.0f}, {3.0f}, {2.0f}, fprop);
}

TEST_P(BackpropTest, BackwardIdenticalInputs) {
    CheckBackprop({2.0f}, {}, {2.0f}, [](auto& xs, __attribute__((unused)) auto& ys) { return xs[0] + xs[0]; });
}

TEST_P(BackpropTest, BackwardGivenInputGrad) {
    auto fprop = [](auto& xs, __attribute__((unused)) auto& ys) {
        xs[0].set_grad(Array::OnesLike(xs[0]));
        return xs[0];
    };
    CheckBackprop({1.0f}, {}, {2.0f}, fprop);
}

TEST_P(BackpropTest, BackwardGivenOutputGrad) {
    auto x = Array::Ones({1}, TypeToDtype<float>);
    x.set_requires_grad(true);
    auto y = x;
    y.set_grad(Array::FullLike(y, 2.0f));
    Backward(y);
    auto e = Array::FullLike(x, 2.0f);
    ExpectEqual<float>(e, *x.grad());
}

INSTANTIATE_TEST_CASE_P(ForEachDevice, BackpropTest, ::testing::Values(
#ifdef XCHAINER_ENABLE_CUDA
                                                         std::string{"cuda"},
#endif  // XCHAINER_ENABLE_CUDA
                                                         std::string{"cpu"}));

}  // namespace
}  // namespace xchainer
<|endoftext|>


<commit_before>#include "xchainer/native/im2col.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/constant.h"
#include "xchainer/device.h"
#include "xchainer/indexable_array.h"
#include "xchainer/indexer.h"
#include "xchainer/macro.h"
#include "xchainer/routines/connection.h"
#include "xchainer/routines/creation.h"
#include "xchainer/scalar.h"
#include "xchainer/shape.h"
#include "xchainer/slice.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace native {
namespace native_internal {

Array Im2Col(
        const Array& x,
        const StackVector<int64_t, kMaxNdim>& kernel_size,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all,
        Scalar pad_value) {
    auto ndim = static_cast<int8_t>(kernel_size.size());  // Number of input image dimensions.
    assert(ndim == static_cast<int8_t>(stride.size()));
    assert(ndim == static_cast<int8_t>(pad.size()));
    assert(ndim + 2 == x.ndim());  // Batch and channel dimensions.

    Device& device = x.device();

    // Create a padded copy of the input image.
    // TODO(hvy): Use the Pad function when implemented.
    Shape padded_shape = x.shape();
    std::vector<ArrayIndex> unpadded_slice{ArrayIndex{Slice{}}, ArrayIndex{Slice{}}};  // All batch and channel dimensions.
    for (int64_t i = 0; i < ndim; ++i) {
        padded_shape[i + 2] += pad[i] * 2 + (cover_all ? stride[i] - 1 : 0);  // Pad on both sides.
        unpadded_slice.emplace_back(Slice{pad[i], pad[i] + x.shape()[i + 2]});
    }
    Array padded_x = static_cast<int64_t>(pad_value) == int64_t{0} ? Zeros(padded_shape, x.dtype(), device)
                                                                   : Full(padded_shape, pad_value, x.dtype(), device);
    device.Copy(x, padded_x.At(unpadded_slice));
    assert(ndim + 2 == padded_x.ndim());

    // Create the output array.
    StackVector<int64_t, kMaxNdim> out_dims;  // Number of patches along each axis
    for (int8_t i = 0; i < ndim; ++i) {
        out_dims.emplace_back(internal::GetConvOutDim(x.shape()[i + 2], kernel_size[i], stride[i], pad[i], cover_all));
        assert(out_dims.back() > 0);
    }
    assert(ndim == static_cast<int8_t>(out_dims.size()));

    int64_t batch_size = x.shape()[0];
    int64_t channels = x.shape()[1];

    Shape out_shape{batch_size, channels};
    std::copy(kernel_size.begin(), kernel_size.end(), std::back_inserter(out_shape));
    std::copy(out_dims.begin(), out_dims.end(), std::back_inserter(out_shape));
    Array out = Empty(out_shape, x.dtype(), device);
    assert(ndim * 2 + 2 == out.ndim());

    // Write to the output array.
    VisitDtype(x.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        Indexer<2> batch_channel_indexer{Shape{batch_size, channels}};

        switch (ndim) {
            case 0:
                Im2ColImpl<T, 0>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 1:
                Im2ColImpl<T, 1>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 2:
                Im2ColImpl<T, 2>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 3:
                Im2ColImpl<T, 3>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 4:
                Im2ColImpl<T, 4>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            default:
                XCHAINER_NEVER_REACH();  // Never out.ndim() > kMaxNdim(10)
                break;
        }
    });

    return out;
}

}  // namespace native_internal
}  // namespace native
}  // namespace xchainer
<commit_msg>static_assert<commit_after>#include "xchainer/native/im2col.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/constant.h"
#include "xchainer/device.h"
#include "xchainer/indexable_array.h"
#include "xchainer/indexer.h"
#include "xchainer/macro.h"
#include "xchainer/routines/connection.h"
#include "xchainer/routines/creation.h"
#include "xchainer/scalar.h"
#include "xchainer/shape.h"
#include "xchainer/slice.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace native {
namespace native_internal {

Array Im2Col(
        const Array& x,
        const StackVector<int64_t, kMaxNdim>& kernel_size,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        bool cover_all,
        Scalar pad_value) {
    auto ndim = static_cast<int8_t>(kernel_size.size());  // Number of input image dimensions.
    assert(ndim == static_cast<int8_t>(stride.size()));
    assert(ndim == static_cast<int8_t>(pad.size()));
    assert(ndim + 2 == x.ndim());  // Batch and channel dimensions.

    Device& device = x.device();

    // Create a padded copy of the input image.
    // TODO(hvy): Use the Pad function when implemented.
    Shape padded_shape = x.shape();
    std::vector<ArrayIndex> unpadded_slice{ArrayIndex{Slice{}}, ArrayIndex{Slice{}}};  // All batch and channel dimensions.
    for (int64_t i = 0; i < ndim; ++i) {
        padded_shape[i + 2] += pad[i] * 2 + (cover_all ? stride[i] - 1 : 0);  // Pad on both sides.
        unpadded_slice.emplace_back(Slice{pad[i], pad[i] + x.shape()[i + 2]});
    }
    Array padded_x = static_cast<int64_t>(pad_value) == int64_t{0} ? Zeros(padded_shape, x.dtype(), device)
                                                                   : Full(padded_shape, pad_value, x.dtype(), device);
    device.Copy(x, padded_x.At(unpadded_slice));
    assert(ndim + 2 == padded_x.ndim());

    // Create the output array.
    StackVector<int64_t, kMaxNdim> out_dims;  // Number of patches along each axis
    for (int8_t i = 0; i < ndim; ++i) {
        out_dims.emplace_back(internal::GetConvOutDim(x.shape()[i + 2], kernel_size[i], stride[i], pad[i], cover_all));
        assert(out_dims.back() > 0);
    }
    assert(ndim == static_cast<int8_t>(out_dims.size()));

    int64_t batch_size = x.shape()[0];
    int64_t channels = x.shape()[1];

    Shape out_shape{batch_size, channels};
    std::copy(kernel_size.begin(), kernel_size.end(), std::back_inserter(out_shape));
    std::copy(out_dims.begin(), out_dims.end(), std::back_inserter(out_shape));
    Array out = Empty(out_shape, x.dtype(), device);
    assert(ndim * 2 + 2 == out.ndim());

    // Write to the output array.
    VisitDtype(x.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        Indexer<2> batch_channel_indexer{Shape{batch_size, channels}};

        switch (ndim) {
            case 0:
                Im2ColImpl<T, 0>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 1:
                Im2ColImpl<T, 1>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 2:
                Im2ColImpl<T, 2>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 3:
                Im2ColImpl<T, 3>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            case 4:
                Im2ColImpl<T, 4>(padded_x, out, kernel_size, stride, out_dims, batch_channel_indexer);
                break;
            default:
                static_assert(kMaxNdim == 10, "kMaxNdim equals to 10");
                XCHAINER_NEVER_REACH();  // Never out.ndim() > kMaxNdim
                break;
        }
    });

    return out;
}

}  // namespace native_internal
}  // namespace native
}  // namespace xchainer
<|endoftext|>