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

#include "chrome/browser/extensions/api/autotest_private/autotest_private_api.h"

#include "base/strings/string_number_conversions.h"
#include "chrome/browser/extensions/api/autotest_private/autotest_private_api_factory.h"
#include "chrome/browser/extensions/extension_function_registry.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/extensions/api/autotest_private.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#endif

namespace extensions {

bool AutotestPrivateLogoutFunction::RunImpl() {
  DVLOG(1) << "AutotestPrivateLogoutFunction";
  if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
    chrome::AttemptUserExit();
  return true;
}

bool AutotestPrivateRestartFunction::RunImpl() {
  DVLOG(1) << "AutotestPrivateRestartFunction";
  if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
    chrome::AttemptRestart();
  return true;
}

bool AutotestPrivateShutdownFunction::RunImpl() {
  scoped_ptr<api::autotest_private::Shutdown::Params> params(
      api::autotest_private::Shutdown::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  DVLOG(1) << "AutotestPrivateShutdownFunction " << params->force;

#if defined(OS_CHROME)
  if (params->force) {
    if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
      chrome::ExitCleanly();
    return true;
  }
#endif
  if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
    chrome::AttemptExit();
  return true;
}

bool AutotestPrivateLoginStatusFunction::RunImpl() {
  DVLOG(1) << "AutotestPrivateLoginStatusFunction";

  DictionaryValue* result(new DictionaryValue);
#if defined(OS_CHROMEOS)
  const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
  const bool is_screen_locked =
      !!chromeos::ScreenLocker::default_screen_locker();

  if (user_manager) {
    result->SetBoolean("isLoggedIn", user_manager->IsUserLoggedIn());
    result->SetBoolean("isOwner", user_manager->IsCurrentUserOwner());
    result->SetBoolean("isScreenLocked", is_screen_locked);
    if (user_manager->IsUserLoggedIn()) {
      result->SetBoolean("isRegularUser",
                         user_manager->IsLoggedInAsRegularUser());
      result->SetBoolean("isGuest", user_manager->IsLoggedInAsGuest());
      result->SetBoolean("isKiosk", user_manager->IsLoggedInAsKioskApp());

      const chromeos::User* user = user_manager->GetLoggedInUser();
      result->SetString("email", user->email());
      result->SetString("displayEmail", user->display_email());

      std::string user_image;
      switch (user->image_index()) {
        case chromeos::User::kExternalImageIndex:
          user_image = "file";
          break;

        case chromeos::User::kProfileImageIndex:
          user_image = "profile";
          break;

        default:
          user_image = base::IntToString(user->image_index());
          break;
      }
      result->SetString("userImage", user_image);
    }
  }
#endif

  SetResult(result);
  return true;
}

AutotestPrivateAPI::AutotestPrivateAPI() : test_mode_(false) {
}

AutotestPrivateAPI::~AutotestPrivateAPI() {
}

}  // namespace extensions
<commit_msg>Cleanup a few probably-incorrect OS_<random> uses.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/api/autotest_private/autotest_private_api.h"

#include "base/strings/string_number_conversions.h"
#include "chrome/browser/extensions/api/autotest_private/autotest_private_api_factory.h"
#include "chrome/browser/extensions/extension_function_registry.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/extensions/api/autotest_private.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#endif

namespace extensions {

bool AutotestPrivateLogoutFunction::RunImpl() {
  DVLOG(1) << "AutotestPrivateLogoutFunction";
  if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
    chrome::AttemptUserExit();
  return true;
}

bool AutotestPrivateRestartFunction::RunImpl() {
  DVLOG(1) << "AutotestPrivateRestartFunction";
  if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
    chrome::AttemptRestart();
  return true;
}

bool AutotestPrivateShutdownFunction::RunImpl() {
  scoped_ptr<api::autotest_private::Shutdown::Params> params(
      api::autotest_private::Shutdown::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  DVLOG(1) << "AutotestPrivateShutdownFunction " << params->force;

#if defined(OS_CHROMEOS)
  if (params->force) {
    if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
      chrome::ExitCleanly();
    return true;
  }
#endif
  if (!AutotestPrivateAPIFactory::GetForProfile(profile())->test_mode())
    chrome::AttemptExit();
  return true;
}

bool AutotestPrivateLoginStatusFunction::RunImpl() {
  DVLOG(1) << "AutotestPrivateLoginStatusFunction";

  DictionaryValue* result(new DictionaryValue);
#if defined(OS_CHROMEOS)
  const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
  const bool is_screen_locked =
      !!chromeos::ScreenLocker::default_screen_locker();

  if (user_manager) {
    result->SetBoolean("isLoggedIn", user_manager->IsUserLoggedIn());
    result->SetBoolean("isOwner", user_manager->IsCurrentUserOwner());
    result->SetBoolean("isScreenLocked", is_screen_locked);
    if (user_manager->IsUserLoggedIn()) {
      result->SetBoolean("isRegularUser",
                         user_manager->IsLoggedInAsRegularUser());
      result->SetBoolean("isGuest", user_manager->IsLoggedInAsGuest());
      result->SetBoolean("isKiosk", user_manager->IsLoggedInAsKioskApp());

      const chromeos::User* user = user_manager->GetLoggedInUser();
      result->SetString("email", user->email());
      result->SetString("displayEmail", user->display_email());

      std::string user_image;
      switch (user->image_index()) {
        case chromeos::User::kExternalImageIndex:
          user_image = "file";
          break;

        case chromeos::User::kProfileImageIndex:
          user_image = "profile";
          break;

        default:
          user_image = base::IntToString(user->image_index());
          break;
      }
      result->SetString("userImage", user_image);
    }
  }
#endif

  SetResult(result);
  return true;
}

AutotestPrivateAPI::AutotestPrivateAPI() : test_mode_(false) {
}

AutotestPrivateAPI::~AutotestPrivateAPI() {
}

}  // namespace extensions
<|endoftext|>


<commit_before>#ifndef __WORD_TAG_HPP__
#define __WORD_TAG_HPP__

#include <vector>
#include <map>
#include <set>

#include "link-includes.h"

extern "C" {
#include "count.h"
#include "prune.h"
#include "word-utils.h"
};

#include "variables.hpp"

struct PositionConnector
{
  PositionConnector(Exp* e, Connector* c, char d, int w, int p,
                    double cst, double pcst, bool lr, bool ll,
                    const std::vector<int>& er, const std::vector<int>& el, const X_node *w_xnode)
    : exp(e), dir(d), word(w), position(p),
      cost(cst), parent_cost(pcst),
      leading_right(lr), leading_left(ll),
      eps_right(er), eps_left(el), word_xnode(w_xnode)
  {
    // Initialize some fields in the connector struct.
    connector.string = c->string;
    connector.multi = c->multi;
    connector.length_limit = c->length_limit;

    if (word_xnode == NULL) {
       cerr << "Internal error: Word" << w << ": " << "; connector: '" << c->string << "'; X_node: " << (word_xnode?word_xnode->string: "(null)") << endl;
    }

    /*
    cout << c->string << " : ." << w << ". : ." << p << ". ";
    if (leading_right) {
      cout << "lr: ";
      copy(er.begin(), er.end(), ostream_iterator<int>(cout, " "));
    }
    if (leading_left) {
      cout << "ll: ";
      copy(el.begin(), el.end(), ostream_iterator<int>(cout, " "));
    }
    cout << endl;
    */
  }

  // Original expression that this connector came from
  Exp* exp;

  // Connector itself
  Connector connector;
  // Direction
  char dir;
  // word in a sentence that this connector belongs to
  size_t word;
  // position in the word tag
  int position;
  // cost of the connector
  double cost;
  // parent cost
  double parent_cost;

  bool leading_right;
  bool leading_left;
  std::vector<int> eps_right;
  std::vector<int> eps_left;

  // The corresponding X_node - chosen-disjuncts[]
  const X_node *word_xnode;

  // Matches with other words
  std::vector<PositionConnector*> matches;

};

// XXX TODO: Hash connectors for faster matching

class WordTag
{
private:
  std::vector<PositionConnector> _left_connectors;
  std::vector<PositionConnector> _right_connectors;

  std::vector<char> _dir;
  std::vector<int> _position;

  int _word;
  Variables* _variables;

  Sentence _sent;
  Parse_Options _opts;

  // Could this word tag match a connector (wi, pi)?
  // For each word wi I keep a set of positions pi that can be matched
  std::vector< std::set<int> > _match_possible;
  void set_match_possible(int wj, int pj) {
    _match_possible[wj].insert(pj);
  }

public:
  WordTag(int word, Variables* variables, Sentence sent, Parse_Options opts)
    : _word(word), _variables(variables), _sent(sent), _opts(opts) {
    _match_possible.resize(_sent->length);
    verbosity = opts->verbosity;
    debug = opts->debug;
    test = opts->test;
  }

  const std::vector<PositionConnector>& get_left_connectors() const {
    return _left_connectors;
  }

  const std::vector<PositionConnector>& get_right_connectors() const {
    return _right_connectors;
  }

  PositionConnector* get(int dfs_position)
  {
    switch (_dir[dfs_position - 1]) {
    case '+':
      return &_right_connectors[_position[dfs_position - 1]];
    case '-':
      return &_left_connectors[_position[dfs_position - 1]];
    }
    return NULL;
  }

  void set_connector_length_limit(Connector* c)
  {
    unsigned int len = _opts->short_length;
    Connector_set * conset = _sent->dict->unlimited_connector_set;

    if (len > UNLIMITED_LEN) len = UNLIMITED_LEN;

    if (_opts->all_short ||
        !(conset == NULL || match_in_connector_set(conset, c)))
	 {
      c->length_limit = len;
    }
  }

  bool match(int w1, Connector& cntr1, char dir, int w2, Connector& cntr2)
  {
      int dist = w2 - w1;
      assert(0 < dist, "match() did not receive words in the natural order.");
      if (dist > cntr1.length_limit || dist > cntr2.length_limit) return false;
      return easy_match(cntr1.string, cntr2.string);
  }

  void insert_connectors(Exp* exp, int& dfs_position,
                         bool& leading_right, bool& leading_left,
                         std::vector<int>& eps_right,
                         std::vector<int>& eps_left,
                         char* var, bool root, double parent_cost,
                         Exp* parent, const X_node *word_xnode);

  // Caches information about the found matches to the _matches vector, and also
  // updates the _matches vector of all connectors in the given tag.
  // In order to have all possible matches correctly cached, the function assumes that it is
  // iteratively called for all words in the sentence, where the tag is on the right side of
  // this word
  void add_matches_with_word(WordTag& tag);

  // Find matches in this word tag with the connector (name, dir).
  void find_matches(int w, const char* C, char dir,  std::vector<PositionConnector*>& matches);

  // A simpler function: Can any connector in this word match a connector wi, pi?
  // It is assumed that
  bool match_possible(int wi, int pi)
  {
    return _match_possible[wi].find(pi) != _match_possible[wi].end();
  }

private:
  int verbosity;
  const char *debug;
  const char *test;
};

#endif
<commit_msg>SAT-solver: Revert the last change of setting length_limit<commit_after>#ifndef __WORD_TAG_HPP__
#define __WORD_TAG_HPP__

#include <vector>
#include <map>
#include <set>

#include "link-includes.h"

extern "C" {
#include "count.h"
#include "prune.h"
#include "word-utils.h"
};

#include "variables.hpp"

struct PositionConnector
{
  PositionConnector(Exp* e, Connector* c, char d, int w, int p,
                    double cst, double pcst, bool lr, bool ll,
                    const std::vector<int>& er, const std::vector<int>& el, const X_node *w_xnode)
    : exp(e), dir(d), word(w), position(p),
      cost(cst), parent_cost(pcst),
      leading_right(lr), leading_left(ll),
      eps_right(er), eps_left(el), word_xnode(w_xnode)
  {
    // Initialize some fields in the connector struct.
    connector.string = c->string;
    connector.multi = c->multi;
    connector.length_limit = c->length_limit;

    if (word_xnode == NULL) {
       cerr << "Internal error: Word" << w << ": " << "; connector: '" << c->string << "'; X_node: " << (word_xnode?word_xnode->string: "(null)") << endl;
    }

    /*
    cout << c->string << " : ." << w << ". : ." << p << ". ";
    if (leading_right) {
      cout << "lr: ";
      copy(er.begin(), er.end(), ostream_iterator<int>(cout, " "));
    }
    if (leading_left) {
      cout << "ll: ";
      copy(el.begin(), el.end(), ostream_iterator<int>(cout, " "));
    }
    cout << endl;
    */
  }

  // Original expression that this connector came from
  Exp* exp;

  // Connector itself
  Connector connector;
  // Direction
  char dir;
  // word in a sentence that this connector belongs to
  size_t word;
  // position in the word tag
  int position;
  // cost of the connector
  double cost;
  // parent cost
  double parent_cost;

  bool leading_right;
  bool leading_left;
  std::vector<int> eps_right;
  std::vector<int> eps_left;

  // The corresponding X_node - chosen-disjuncts[]
  const X_node *word_xnode;

  // Matches with other words
  std::vector<PositionConnector*> matches;

};

// XXX TODO: Hash connectors for faster matching

class WordTag
{
private:
  std::vector<PositionConnector> _left_connectors;
  std::vector<PositionConnector> _right_connectors;

  std::vector<char> _dir;
  std::vector<int> _position;

  int _word;
  Variables* _variables;

  Sentence _sent;
  Parse_Options _opts;

  // Could this word tag match a connector (wi, pi)?
  // For each word wi I keep a set of positions pi that can be matched
  std::vector< std::set<int> > _match_possible;
  void set_match_possible(int wj, int pj) {
    _match_possible[wj].insert(pj);
  }

public:
  WordTag(int word, Variables* variables, Sentence sent, Parse_Options opts)
    : _word(word), _variables(variables), _sent(sent), _opts(opts) {
    _match_possible.resize(_sent->length);
    verbosity = opts->verbosity;
    debug = opts->debug;
    test = opts->test;
  }

  const std::vector<PositionConnector>& get_left_connectors() const {
    return _left_connectors;
  }

  const std::vector<PositionConnector>& get_right_connectors() const {
    return _right_connectors;
  }

  PositionConnector* get(int dfs_position)
  {
    switch (_dir[dfs_position - 1]) {
    case '+':
      return &_right_connectors[_position[dfs_position - 1]];
    case '-':
      return &_left_connectors[_position[dfs_position - 1]];
    }
    return NULL;
  }

  void set_connector_length_limit(Connector* c)
  {
    unsigned int len = _opts->short_length;
    Connector_set * conset = _sent->dict->unlimited_connector_set;

    if (len > UNLIMITED_LEN) len = UNLIMITED_LEN;

    if (_opts->all_short ||
        (conset != NULL && !match_in_connector_set(conset, c)))
  {
      c->length_limit = len;
    }
    else {
      c->length_limit = UNLIMITED_LEN;
    }
  }

  bool match(int w1, Connector& cntr1, char dir, int w2, Connector& cntr2)
  {
      int dist = w2 - w1;
      assert(0 < dist, "match() did not receive words in the natural order.");
      if (dist > cntr1.length_limit || dist > cntr2.length_limit) return false;
      return easy_match(cntr1.string, cntr2.string);
  }

  void insert_connectors(Exp* exp, int& dfs_position,
                         bool& leading_right, bool& leading_left,
                         std::vector<int>& eps_right,
                         std::vector<int>& eps_left,
                         char* var, bool root, double parent_cost,
                         Exp* parent, const X_node *word_xnode);

  // Caches information about the found matches to the _matches vector, and also
  // updates the _matches vector of all connectors in the given tag.
  // In order to have all possible matches correctly cached, the function assumes that it is
  // iteratively called for all words in the sentence, where the tag is on the right side of
  // this word
  void add_matches_with_word(WordTag& tag);

  // Find matches in this word tag with the connector (name, dir).
  void find_matches(int w, const char* C, char dir,  std::vector<PositionConnector*>& matches);

  // A simpler function: Can any connector in this word match a connector wi, pi?
  // It is assumed that
  bool match_possible(int wi, int pi)
  {
    return _match_possible[wi].find(pi) != _match_possible[wi].end();
  }

private:
  int verbosity;
  const char *debug;
  const char *test;
};

#endif
<|endoftext|>


<commit_before>// Copyright(c) Andre Caron, 2009-2010
//
// This document is covered by the Artistic License 2.0 (Open Source Initiative
// approved license). A copy of the license should have been provided alongside
// this software package (see "license.rtf"). If not, the license is available
// online at "http://www.opensource.org/licenses/artistic-license-2.0.php".

#include <w32/string.hpp>
#include <w32/astring.hpp>
#include <w32/Error.hpp>
#include <algorithm>
#include <iostream>
#include <limits>
#include <cstring>

namespace {

        // Allocate a string and automatically terminate it.
    template<typename T>
    T * allocate ( ::DWORD size )
    {
        T *const result = new T[size+1];
        result[size] = T(0);
        return (result);
    }

        // Returns the number of characters to allocate.
    template<typename T>
    ::DWORD count ( const T * value )
    {
        static const T terminator(0);
        ::DWORD result = 0;
        for ( ; (*value != terminator); ++value ) {
            ++result;
        }
        return (result);
    }

        // Allocate a fresh copy of a string.
    template<typename T>
    T * duplicate ( ::DWORD size, const T * value )
    {
        T *const result = allocate<T>(size);
        ::memcpy(result, value, sizeof(T)*size);
        return (result);
    }

        // Request the number of characters to allocate.
    ::DWORD count ( ::UINT codepage, const char * value )
    {
        const int result = ::MultiByteToWideChar(
                               codepage, 0, value, -1, 0, 0
                           );
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (result);
    }

        // Codepage is source encoding!
    ::WCHAR * decode ( ::UINT codepage, ::DWORD size, const char * value )
    {
        ::WCHAR *const data = allocate<::WCHAR>(size);
        const int result = ::MultiByteToWideChar(codepage,0,value,-1,data,size+1);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (data);
    }

}

namespace w32 {

    const string::size_type string::npos =
        std::numeric_limits< string::size_type >::max();

    string::string ()
        : mySize(0),
          myData(::duplicate(mySize, L""))
    {
    }

    string::string ( const char * other, Codepage encoding )
        : mySize(::count(other)),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const char * other, size_type size, Codepage encoding )
        : mySize(size),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const astring& other )
        : mySize(other.size()),
          myData(decode(other.encoding(), mySize, other.data()))
    {
    }

    string::string ( const std::string& other, Codepage encoding )
        : mySize(other.size()),
          myData(::decode(encoding, mySize, other.data()))
    {
    }

    string::string ( const_pointer other )
        : mySize(count(other)),
          myData(duplicate(mySize,other))
    {
    }

    string::string ( const_pointer other, size_type size )
        : mySize(size),
          myData(duplicate(mySize,other))
    {
    }
    string::string ( const box& value )
        : mySize(value.size()),
          myData(value.data())
    {
    }

    string::string ( size_type size, char_type filler )
        : mySize(size),
          myData(::allocate<wchar_t>(size))
    {
        std::fill(begin(), end(), filler);
    }

    string::string ( const string& other )
        : mySize(other.size()),
          myData(duplicate(mySize,other.data()))
    {
    }

    string::~string ()
    {
        delete [] myData;
        myData = 0;
        mySize = 0;
    }

    string::size_type string::size() const
    {
        return (mySize);
    }

    string::size_type string::length() const
    {
        return (mySize);
    }

    bool string::empty () const
    {
        return (size() == 0);
    }

    string::pointer string::data ()
    {
        return (myData);
    }

    string::const_pointer string::data () const
    {
        return (myData);
    }

    string::pointer string::c_str ()
    {
        return (myData);
    }

    string::const_pointer string::c_str () const
    {
        return (myData);
    }

    void string::erase ( iterator begin, iterator end )
    {
            // Copy trailing characters.
        end = std::copy(end, myData+mySize, begin);

            // Terminate string.
        myData[mySize = (end-myData)] = L'\0';
    }

    void string::resize ( size_type length, wchar_t filler )
    {
            // Don't reallocate when not required to.
        if ( length <= size() ) {
            erase(begin()+size(), end());
        }
        else {
            string other(length, filler);
            std::copy(begin(), end(), other.begin());
            swap(other);
        }
    }

    void string::clear ()
    {
        erase(begin(), end());
    }

    string string::substr ( size_type offset, size_type length ) const
    {
        offset = std::min(offset,        size());
        length = std::min(offset+length, size());
        return (string(data()+offset, length));
    }

    string::iterator string::begin ()
    {
        return (data());
    }

    string::iterator string::end ()
    {
        return (data() + size());
    }

    string::const_iterator string::begin () const
    {
        return (data());
    }

    string::const_iterator string::end () const
    {
        return (data() + size());
    }

    void string::swap ( string& other )
    {
        std::swap(mySize,other.mySize);
        std::swap(myData,other.myData);
    }

    string& string::operator= ( const string& other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const_pointer other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const std::wstring& other )
    {
        string copy(other.c_str());
        copy.swap(*this);
        return (*this);
    }

    bool string::operator== ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) == 0);
    }

    bool string::operator!= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) != 0);
    }

    string& string::operator+= ( const string& rhs )
    {
        if ( length() == 0 ) {
            return ((*this) = rhs);
        }
        string result(length() + rhs.length());
        std::copy(rhs.begin(), rhs.end(),
            std::copy(begin(), end(), result.begin()));
        result.swap(*this);
        return (*this);
    }

    string string::operator+ ( const string& rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string& string::operator+= ( wchar_t rhs )
    {
        resize(1+size());
        (*this)[size()-1] = rhs;
        return (*this);
    }

    string string::operator+ ( wchar_t rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string operator+ ( const wchar_t * lhs, const string& rhs )
    {
        return (string(lhs) + rhs);
    }

    std::wostream& operator<< ( std::wostream& out, const string& value )
    {
        return (out << value.data());
    }

    string::box::box ( pointer data )
        : mySize(std::wcslen(data)), myData(data)
    {
    }

    string::box::box ( pointer data, size_type size )
        : mySize(size), myData(data)
    {
    }

    string::size_type string::box::size() const
    {
        return (mySize);
    }

    string::pointer string::box::data () const
    {
        return (myData);
    }

}
<commit_msg>Prevented crash on null pointer in string constructor.<commit_after>// Copyright(c) Andre Caron, 2009-2010
//
// This document is covered by the Artistic License 2.0 (Open Source Initiative
// approved license). A copy of the license should have been provided alongside
// this software package (see "license.rtf"). If not, the license is available
// online at "http://www.opensource.org/licenses/artistic-license-2.0.php".

#include <w32/string.hpp>
#include <w32/astring.hpp>
#include <w32/Error.hpp>
#include <algorithm>
#include <iostream>
#include <limits>
#include <cstring>

namespace {

        // Allocate a string and automatically terminate it.
    template<typename T>
    T * allocate ( ::DWORD size )
    {
        T *const result = new T[size+1];
        result[size] = T(0);
        return (result);
    }

        // Returns the number of characters to allocate.
    template<typename T>
    ::DWORD count ( const T * value )
    {
        if ( value == 0 ) {
            return (0);
        }
        static const T terminator(0);
        ::DWORD result = 0;
        for ( ; (*value != terminator); ++value ) {
            ++result;
        }
        return (result);
    }

        // Allocate a fresh copy of a string.
    template<typename T>
    T * duplicate ( ::DWORD size, const T * value )
    {
        T *const result = allocate<T>(size);
        ::memcpy(result, value, sizeof(T)*size);
        return (result);
    }

        // Request the number of characters to allocate.
    ::DWORD count ( ::UINT codepage, const char * value )
    {
        const int result = ::MultiByteToWideChar
            (codepage, 0, value, -1, 0, 0);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (result);
    }

        // Codepage is source encoding!
    ::WCHAR * decode ( ::UINT codepage, ::DWORD size, const char * value )
    {
        ::WCHAR *const data = allocate<::WCHAR>(size);
        const int result = ::MultiByteToWideChar(codepage,0,value,-1,data,size+1);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (data);
    }

}

namespace w32 {

    const string::size_type string::npos =
        std::numeric_limits< string::size_type >::max();

    string::string ()
        : mySize(0),
          myData(::duplicate(mySize, L""))
    {
    }

    string::string ( const char * other, Codepage encoding )
        : mySize(::count(other)),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const char * other, size_type size, Codepage encoding )
        : mySize(size),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const astring& other )
        : mySize(other.size()),
          myData(decode(other.encoding(), mySize, other.data()))
    {
    }

    string::string ( const std::string& other, Codepage encoding )
        : mySize(other.size()),
          myData(::decode(encoding, mySize, other.data()))
    {
    }

    string::string ( const_pointer other )
        : mySize(count(other)),
          myData(duplicate(mySize,other))
    {
    }

    string::string ( const_pointer other, size_type size )
        : mySize(size),
          myData(duplicate(mySize,other))
    {
    }
    string::string ( const box& value )
        : mySize(value.size()),
          myData(value.data())
    {
    }

    string::string ( size_type size, char_type filler )
        : mySize(size),
          myData(::allocate<wchar_t>(size))
    {
        std::fill(begin(), end(), filler);
    }

    string::string ( const string& other )
        : mySize(other.size()),
          myData(duplicate(mySize,other.data()))
    {
    }

    string::~string ()
    {
        delete [] myData;
        myData = 0;
        mySize = 0;
    }

    string::size_type string::size() const
    {
        return (mySize);
    }

    string::size_type string::length() const
    {
        return (mySize);
    }

    bool string::empty () const
    {
        return (size() == 0);
    }

    string::pointer string::data ()
    {
        return (myData);
    }

    string::const_pointer string::data () const
    {
        return (myData);
    }

    string::pointer string::c_str ()
    {
        return (myData);
    }

    string::const_pointer string::c_str () const
    {
        return (myData);
    }

    void string::erase ( iterator begin, iterator end )
    {
            // Copy trailing characters.
        end = std::copy(end, myData+mySize, begin);

            // Terminate string.
        myData[mySize = (end-myData)] = L'\0';
    }

    void string::resize ( size_type length, wchar_t filler )
    {
            // Don't reallocate when not required to.
        if ( length <= size() ) {
            erase(begin()+size(), end());
        }
        else {
            string other(length, filler);
            std::copy(begin(), end(), other.begin());
            swap(other);
        }
    }

    void string::clear ()
    {
        erase(begin(), end());
    }

    string string::substr ( size_type offset, size_type length ) const
    {
        offset = std::min(offset,        size());
        length = std::min(offset+length, size());
        return (string(data()+offset, length));
    }

    string::iterator string::begin ()
    {
        return (data());
    }

    string::iterator string::end ()
    {
        return (data() + size());
    }

    string::const_iterator string::begin () const
    {
        return (data());
    }

    string::const_iterator string::end () const
    {
        return (data() + size());
    }

    void string::swap ( string& other )
    {
        std::swap(mySize,other.mySize);
        std::swap(myData,other.myData);
    }

    string& string::operator= ( const string& other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const_pointer other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const std::wstring& other )
    {
        string copy(other.c_str());
        copy.swap(*this);
        return (*this);
    }

    bool string::operator== ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) == 0);
    }

    bool string::operator!= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) != 0);
    }

    string& string::operator+= ( const string& rhs )
    {
        if ( length() == 0 ) {
            return ((*this) = rhs);
        }
        string result(length() + rhs.length());
        std::copy(rhs.begin(), rhs.end(),
            std::copy(begin(), end(), result.begin()));
        result.swap(*this);
        return (*this);
    }

    string string::operator+ ( const string& rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string& string::operator+= ( wchar_t rhs )
    {
        resize(1+size());
        (*this)[size()-1] = rhs;
        return (*this);
    }

    string string::operator+ ( wchar_t rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string operator+ ( const wchar_t * lhs, const string& rhs )
    {
        return (string(lhs) + rhs);
    }

    std::wostream& operator<< ( std::wostream& out, const string& value )
    {
        return (out << value.data());
    }

    string::box::box ( pointer data )
        : mySize(std::wcslen(data)), myData(data)
    {
    }

    string::box::box ( pointer data, size_type size )
        : mySize(size), myData(data)
    {
    }

    string::size_type string::box::size() const
    {
        return (mySize);
    }

    string::pointer string::box::data () const
    {
        return (myData);
    }

}
<|endoftext|>


<commit_before>#include "ncserver.h"
#include "networkcodingheader.h"
#include "finite_field.h"
#include <exception>
#include <string.h>

ncserver::ncserver(unsigned int client_ip, unsigned short int port, unsigned char max_block_size, unsigned int timeout):\
                                    _CTRL_ADDR(build_addr(INADDR_ANY, port)), _DATA_ADDR(build_addr(client_ip, port)), \
                                    _MAX_BLOCK_SIZE(max_block_size), _TX_TIMEOUT(timeout){
    _socket = 0;
    _tx_cnt = 0;
    _blk_seq = 0;
    _pkt_seq = 0;
    _redundant_pkts = 2;

	/*
	 * TODO: 1) Encode meaningful pkts in _buffer. (_buffer may not be full when _flush_pkts is triggered by timeout)
	 *       2) The length of remedy packet should be as most that of the longest pkt in _buffer.
	 *       3) Parallelize the encoding process using OpenMP.
	 * NOTE: 1) This function should be called by singleshottimer. Otherwise, its operation is undefied.
	 */
	_cancel_callback = _timeout_callback = [&](){
		std::lock_guard<std::mutex> lock(_lock);

		int ret;
		for(unsigned int tx = 0 ; tx < _redundant_pkts ; tx++){
			for(unsigned int code = 0 ; code < _MAX_BLOCK_SIZE ; code++){
				_rand_coef[code] = 1+rand()%255;
			}
			GET_BLK_SEQ(_remedy_pkt) = _blk_seq;
			GET_PKT_SEQ(_remedy_pkt) = _pkt_seq++;
			GET_BLK_SIZE(_remedy_pkt) = _MAX_BLOCK_SIZE;
			for(unsigned int position = OUTERHEADER_SIZE ; position < HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE) ; position++){
				for(unsigned int pkt = 0 ; pkt < _MAX_BLOCK_SIZE ; pkt++){
					(pkt == 0?
						_remedy_pkt[pos] = FiniteField::instance()->mul(_buffer[pkt][position], _rand_coef[pkt]):
						_remedy_pkt[pos] ^= FiniteField::instance()->mul(_buffer[pkt][position], _rand_coef[pkt]));
				}
			}
			ret = sendto(_socket, _remedy_pkt, HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE), 0, (sockaddr*)&_DATA_ADDR, sizeof(_DATA_ADDR));
			if(ret == -1){
				std::cout << "Cannot send remedy pkt" << std::endl;
			}
		}
		_blk_seq++;
		_tx_cnt = 0;
	};
}

ncserver::~ncserver(){
    close_server();
}

sockaddr_in ncserver::build_addr(unsigned int ip, unsigned short int port){
    sockaddr_in ret = {0};
    ret.sin_family = AF_INET;
    ret.sin_addr.s_addr = htonl(ip);
    ret.sin_port = htons(port);
    return ret;
}

bool ncserver::open_server(){
    _socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(_socket == -1){
        return false;
    }
    int opt = 1;
    if(setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1){
        close(_socket);
        return false;
    }
    if(bind(_socket, (sockaddr*)&_CTRL_ADDR, sizeof(_CTRL_ADDR)) == -1){
        close(_socket);
        return false;
    }
    try{
        _buffer = new unsigned char*[_MAX_BLOCK_SIZE];
		for(unsigned int i = 0 ; i < _MAX_BLOCK_SIZE ; i++){
			_buffer[i] = new unsigned char[HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE)];
		}
		_remedy_pkt = new unsigned char[HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE)];
		_rand_coef = new unsigned char[_MAX_BLOCK_SIZE];
    }catch(std::exception &ex){
        return false;
    }
    return true;
}

/*
 * TODO: Check if this function can be further optimized using rvalue reference using std::move()
 */
unsigned short int ncserver::send(unsigned char* pkt, unsigned short int pkt_size){
	std::lock_guard<std::mutex> lock(_lock);
	unsigned short int ret = 0;
	if(pkt_size > MAX_PAYLOAD_SIZE){
		return 0; // I will support pkt_size larger than MAX_PAYLOAD_SIZE in the next phase.
	}

	GET_BLK_SEQ(_buffer[_tx_cnt]) = _blk_seq;

	GET_PKT_SEQ(_buffer[_tx_cnt]) = _pkt_seq++;

	GET_BLK_SIZE(_buffer[_tx_cnt]) = _MAX_BLOCK_SIZE;

	GET_SIZE(_buffer[_tx_cnt]) = pkt_size;

	GET_LAST_INDICATOR(_buffer[_tx_cnt]) = 1; // I will support pkt_size larger than MAX_PAYLOAD_SIZE in the next phase.

	memset(GET_CODE(_buffer[_tx_cnt]), 0x0, _MAX_BLOCK_SIZE);
	GET_CODE(_buffer[_tx_cnt])[_tx_cnt] = 1;

	memcpy(GET_PAYLOAD(_buffer[_tx_cnt], _MAX_BLOCK_SIZE), pkt, pkt_size);

	if(sendto(_socket, _buffer[_tx_cnt], pkt_size + HEADER_SIZE(_MAX_BLOCK_SIZE), 0, (sockaddr*)&_DATA_ADDR, sizeof(_DATA_ADDR)) == pkt_size + HEADER_SIZE(_MAX_BLOCK_SIZE)){
		ret = pkt_size;
	}else{
		ret = 0;
	}
	if(_tx_cnt == 0){
		_timer.start(_TX_TIMEOUT, _cancel_callback, _timeout_callback);
	}else if(_tx_cnt == _MAX_BLOCK_SIZE-1){
		_timer.cancel();
	}
	_tx_cnt++;
	return ret;
}

void ncserver::close_server(){
	delete [] _rand_coef;
	delete [] _remedy_pkt;
    for(unsigned int i = 0 ; i < _MAX_BLOCK_SIZE ; i++){
        delete [] _buffer[i];
    }
    delete []_buffer;

    if(_socket){
        close(_socket);
    }
}
<commit_msg>Update ncserver.cpp<commit_after>#include "ncserver.h"
#include "networkcodingheader.h"
#include "finite_field.h"
#include <exception>
#include <string.h>

ncserver::ncserver(unsigned int client_ip, unsigned short int port, unsigned char max_block_size, unsigned int timeout):\
                                    _CTRL_ADDR(build_addr(INADDR_ANY, port)), _DATA_ADDR(build_addr(client_ip, port)), \
                                    _MAX_BLOCK_SIZE(max_block_size), _TX_TIMEOUT(timeout){
    _socket = 0;
    _tx_cnt = 0;
    _largest_pkt_size = 0;
    _blk_seq = 0;
    _pkt_seq = 0;
    _redundant_pkts = 2;

	/*
	 * TODO: 1) Encode meaningful pkts in _buffer. (_buffer may not be full when _flush_pkts is triggered by timeout) => resolved: for(unsigned int pkt = 0 ; pkt < _tx_cnt ; pkt++){
	 *       2) The length of remedy packet should be as most that of the longest pkt in _buffer. => resolved: HEADER_SIZE(_MAX_BLOCK_SIZE)+_largest_pkt_size
	 *       3) Parallelize the encoding process using OpenMP.
	 * NOTE: 1) This function should be called by singleshottimer. Otherwise, its operation is undefied.
	 */
	_cancel_callback = _timeout_callback = [&](){
		std::lock_guard<std::mutex> lock(_lock);

		int ret;
		for(unsigned int tx = 0 ; tx < _redundant_pkts ; tx++){
			for(unsigned int code = 0 ; code < _MAX_BLOCK_SIZE ; code++){
				_rand_coef[code] = 1+rand()%255;
			}
			GET_BLK_SEQ(_remedy_pkt) = _blk_seq;
			GET_PKT_SEQ(_remedy_pkt) = _pkt_seq++;
			GET_BLK_SIZE(_remedy_pkt) = _MAX_BLOCK_SIZE;
			for(unsigned int position = OUTERHEADER_SIZE ; position < HEADER_SIZE(_MAX_BLOCK_SIZE)+_largest_pkt_size ; position++){
				for(unsigned int pkt = 0 ; pkt < _tx_cnt ; pkt++){
					(pkt == 0?
						_remedy_pkt[pos] = FiniteField::instance()->mul(_buffer[pkt][position], _rand_coef[pkt]):
						_remedy_pkt[pos] ^= FiniteField::instance()->mul(_buffer[pkt][position], _rand_coef[pkt]));
				}
			}
			ret = sendto(_socket, _remedy_pkt, HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE), 0, (sockaddr*)&_DATA_ADDR, sizeof(_DATA_ADDR));
			if(ret == -1){
				std::cout << "Cannot send remedy pkt" << std::endl;
			}
		}
		_blk_seq++;
		_tx_cnt = 0;
		_largest_pkt_size = 0;
	};
}

ncserver::~ncserver(){
    close_server();
}

sockaddr_in ncserver::build_addr(unsigned int ip, unsigned short int port){
    sockaddr_in ret = {0};
    ret.sin_family = AF_INET;
    ret.sin_addr.s_addr = htonl(ip);
    ret.sin_port = htons(port);
    return ret;
}

bool ncserver::open_server(){
    _socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(_socket == -1){
        return false;
    }
    int opt = 1;
    if(setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1){
        close(_socket);
        return false;
    }
    if(bind(_socket, (sockaddr*)&_CTRL_ADDR, sizeof(_CTRL_ADDR)) == -1){
        close(_socket);
        return false;
    }
    try{
        _buffer = new unsigned char*[_MAX_BLOCK_SIZE];
		for(unsigned int i = 0 ; i < _MAX_BLOCK_SIZE ; i++){
			_buffer[i] = new unsigned char[HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE)];
		}
		_remedy_pkt = new unsigned char[HEADER_SIZE(_MAX_BLOCK_SIZE)+MAX_PAYLOAD_SIZE(_MAX_BLOCK_SIZE)];
		_rand_coef = new unsigned char[_MAX_BLOCK_SIZE];
    }catch(std::exception &ex){
        return false;
    }
    return true;
}

/*
 * TODO: Check if this function can be further optimized using rvalue reference using std::move()
 */
unsigned short int ncserver::send(unsigned char* pkt, unsigned short int pkt_size){
	std::lock_guard<std::mutex> lock(_lock);
	unsigned short int ret = 0;
	if(pkt_size > MAX_PAYLOAD_SIZE){
		return 0; // I will support pkt_size larger than MAX_PAYLOAD_SIZE in the next phase.
	}
	if(_largest_pkt_size < pkt_size){
		_largest_pkt_size = pkt_size;
	}

	GET_BLK_SEQ(_buffer[_tx_cnt]) = _blk_seq;

	GET_PKT_SEQ(_buffer[_tx_cnt]) = _pkt_seq++;

	GET_BLK_SIZE(_buffer[_tx_cnt]) = _MAX_BLOCK_SIZE;

	GET_SIZE(_buffer[_tx_cnt]) = pkt_size;

	GET_LAST_INDICATOR(_buffer[_tx_cnt]) = 1; // I will support pkt_size larger than MAX_PAYLOAD_SIZE in the next phase.

	memset(GET_CODE(_buffer[_tx_cnt]), 0x0, _MAX_BLOCK_SIZE);
	GET_CODE(_buffer[_tx_cnt])[_tx_cnt] = 1;

	memcpy(GET_PAYLOAD(_buffer[_tx_cnt], _MAX_BLOCK_SIZE), pkt, pkt_size);

	if(sendto(_socket, _buffer[_tx_cnt], pkt_size + HEADER_SIZE(_MAX_BLOCK_SIZE), 0, (sockaddr*)&_DATA_ADDR, sizeof(_DATA_ADDR)) == pkt_size + HEADER_SIZE(_MAX_BLOCK_SIZE)){
		ret = pkt_size;
	}else{
		ret = 0;
	}
	if(_tx_cnt == 0){
		_timer.start(_TX_TIMEOUT, _cancel_callback, _timeout_callback);
	}else if(_tx_cnt == _MAX_BLOCK_SIZE-1){
		_timer.cancel();
	}
	_tx_cnt++;
	return ret;
}

void ncserver::close_server(){
	delete [] _rand_coef;
	delete [] _remedy_pkt;
    for(unsigned int i = 0 ; i < _MAX_BLOCK_SIZE ; i++){
        delete [] _buffer[i];
    }
    delete []_buffer;

    if(_socket){
        close(_socket);
    }
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
//
// 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.
//

// Interface header.
#include "shadingresultframebuffer.h"

// appleseed.renderer headers.
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/shading/shadingresult.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/colorspace.h"
#include "foundation/image/tile.h"
#include "foundation/platform/compiler.h"

// Standard headers.
#include <cassert>

using namespace foundation;
using namespace std;

namespace renderer
{

ShadingResultFrameBuffer::ShadingResultFrameBuffer(
    const size_t                    width,
    const size_t                    height,
    const size_t                    aov_count,
    const Filter2d&                 filter)
  : FilteredTile(
        width,
        height,
        4 + aov_count * 3,
        filter)
  , m_aov_count(aov_count)
  , m_scratch(4 + aov_count * 3)
{
}

ShadingResultFrameBuffer::ShadingResultFrameBuffer(
    const size_t                    width,
    const size_t                    height,
    const size_t                    aov_count,
    const AABB2u&                   crop_window,
    const Filter2d&                 filter)
  : FilteredTile(
        width,
        height,
        4 + aov_count * 3,
        crop_window,
        filter)
  , m_aov_count(aov_count)
  , m_scratch(4 + aov_count * 3)
{
}

void ShadingResultFrameBuffer::add(
    const double                    x,
    const double                    y,
    const ShadingResult&            sample)
{
    assert(sample.m_color_space == ColorSpaceLinearRGB);

    float* ptr = &m_scratch[0];

    *ptr++ = sample.m_alpha[0];
    *ptr++ = sample.m_color[0];
    *ptr++ = sample.m_color[1];
    *ptr++ = sample.m_color[2];

    for (size_t i = 0; i < m_aov_count; ++i)
    {
        *ptr++ = sample.m_aovs[i][0];
        *ptr++ = sample.m_aovs[i][1];
        *ptr++ = sample.m_aovs[i][2];
    }

    FilteredTile::add(x, y, &m_scratch[0]);
}

void ShadingResultFrameBuffer::merge(
    const size_t                    dest_x,
    const size_t                    dest_y,
    const ShadingResultFrameBuffer& source,
    const size_t                    source_x,
    const size_t                    source_y,
    const float                     scaling)
{
    assert(m_channel_count == source.m_channel_count);

    const float* RESTRICT source_ptr = source.pixel(source_x, source_y);
    float* RESTRICT dest_ptr = pixel(dest_x, dest_y);

    for (size_t i = 0; i < m_channel_count + 1; ++i)
        dest_ptr[i] += source_ptr[i] * scaling;
}

void ShadingResultFrameBuffer::develop_to_tile_premult_alpha(
    Tile&                           tile,
    TileStack&                      aov_tiles) const
{
    const float* ptr = pixel(0);

    for (size_t y = 0; y < m_height; ++y)
    {
        for (size_t x = 0; x < m_width; ++x)
        {
            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;

            const Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            tile.set_pixel(x, y, color * rcp_weight);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                const Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov_tiles.set_pixel(x, y, i, aov * rcp_weight);
                ptr += 3;
            }
        }
    }
}

void ShadingResultFrameBuffer::develop_to_tile_straight_alpha(
    Tile&                           tile,
    TileStack&                      aov_tiles) const
{
    const float* ptr = pixel(0);

    for (size_t y = 0; y < m_height; ++y)
    {
        for (size_t x = 0; x < m_width; ++x)
        {
            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;
            const float rcp_weight_alpha = alpha == 0.0f ? 0.0f : 1.0f / alpha;

            Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            color.rgb() *= rcp_weight_alpha;
            color.a *= rcp_weight;
            tile.set_pixel(x, y, color);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov.rgb() *= rcp_weight_alpha;
                aov.a *= rcp_weight;
                aov_tiles.set_pixel(x, y, i, aov);
                ptr += 3;
            }
        }
    }
}

}   // namespace renderer
<commit_msg>fixed regression.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
//
// 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.
//

// Interface header.
#include "shadingresultframebuffer.h"

// appleseed.renderer headers.
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/shading/shadingresult.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/colorspace.h"
#include "foundation/image/tile.h"
#include "foundation/platform/compiler.h"

// Standard headers.
#include <cassert>

using namespace foundation;
using namespace std;

namespace renderer
{

ShadingResultFrameBuffer::ShadingResultFrameBuffer(
    const size_t                    width,
    const size_t                    height,
    const size_t                    aov_count,
    const Filter2d&                 filter)
  : FilteredTile(
        width,
        height,
        4 + aov_count * 3,
        filter)
  , m_aov_count(aov_count)
  , m_scratch(4 + aov_count * 3)
{
}

ShadingResultFrameBuffer::ShadingResultFrameBuffer(
    const size_t                    width,
    const size_t                    height,
    const size_t                    aov_count,
    const AABB2u&                   crop_window,
    const Filter2d&                 filter)
  : FilteredTile(
        width,
        height,
        4 + aov_count * 3,
        crop_window,
        filter)
  , m_aov_count(aov_count)
  , m_scratch(4 + aov_count * 3)
{
}

void ShadingResultFrameBuffer::add(
    const double                    x,
    const double                    y,
    const ShadingResult&            sample)
{
    assert(sample.m_color_space == ColorSpaceLinearRGB);

    float* ptr = &m_scratch[0];

    *ptr++ = sample.m_alpha[0];
    *ptr++ = sample.m_color[0];
    *ptr++ = sample.m_color[1];
    *ptr++ = sample.m_color[2];

    for (size_t i = 0; i < m_aov_count; ++i)
    {
        *ptr++ = sample.m_aovs[i][0];
        *ptr++ = sample.m_aovs[i][1];
        *ptr++ = sample.m_aovs[i][2];
    }

    FilteredTile::add(x, y, &m_scratch[0]);
}

void ShadingResultFrameBuffer::merge(
    const size_t                    dest_x,
    const size_t                    dest_y,
    const ShadingResultFrameBuffer& source,
    const size_t                    source_x,
    const size_t                    source_y,
    const float                     scaling)
{
    assert(m_channel_count == source.m_channel_count);

    const float* RESTRICT source_ptr = source.pixel(source_x, source_y);
    float* RESTRICT dest_ptr = pixel(dest_x, dest_y);

    for (size_t i = 0; i < m_channel_count; ++i)
        dest_ptr[i] += source_ptr[i] * scaling;
}

void ShadingResultFrameBuffer::develop_to_tile_premult_alpha(
    Tile&                           tile,
    TileStack&                      aov_tiles) const
{
    const float* ptr = pixel(0);

    for (size_t y = 0; y < m_height; ++y)
    {
        for (size_t x = 0; x < m_width; ++x)
        {
            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;

            const Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            tile.set_pixel(x, y, color * rcp_weight);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                const Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov_tiles.set_pixel(x, y, i, aov * rcp_weight);
                ptr += 3;
            }
        }
    }
}

void ShadingResultFrameBuffer::develop_to_tile_straight_alpha(
    Tile&                           tile,
    TileStack&                      aov_tiles) const
{
    const float* ptr = pixel(0);

    for (size_t y = 0; y < m_height; ++y)
    {
        for (size_t x = 0; x < m_width; ++x)
        {
            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;
            const float rcp_weight_alpha = alpha == 0.0f ? 0.0f : 1.0f / alpha;

            Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            color.rgb() *= rcp_weight_alpha;
            color.a *= rcp_weight;
            tile.set_pixel(x, y, color);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov.rgb() *= rcp_weight_alpha;
                aov.a *= rcp_weight;
                aov_tiles.set_pixel(x, y, i, aov);
                ptr += 3;
            }
        }
    }
}

}   // namespace renderer
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_setup_runtime_wakeup_mode.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file   p9_setup_runtime_wakeup_mode.H
/// @brief  describes HWP interface that configures runtime wakeup mode of core.
///
/// *HWP HWP Owner:      Greg Still <stillgs@us.ibm.com>
/// *HWP FW Owner:       Prem S Jha <premjha2@in.ibm.com>
/// *HWP Team:           PM
/// *HWP Level:          2
/// *HWP Consumed by:    Hostboot
//

#include <p9_setup_runtime_wakeup_mode.H>
#include <p9_quad_scom_addresses.H>

enum
{
    RUN_TIME_WAKEUP_MODE_BIT_POS    =   3,
    HV_COMPATIBILITY_MODE_BIT_POS   =   4,
};

fapi2::ReturnCode p9_setup_runtime_wakeup_mode(
    const fapi2::Target < fapi2::TARGET_TYPE_PROC_CHIP>& i_procTarget )
{
    FAPI_INF("> p9_setup_runtime_wakeup_mode" );
    fapi2::buffer<uint64_t> l_wakeupMode;
    uint8_t l_smfEnabled;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    auto l_coreList =
        i_procTarget.getChildren<fapi2::TARGET_TYPE_CORE>(fapi2::TARGET_STATE_FUNCTIONAL);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SMF_ENABLED,
                           FAPI_SYSTEM,
                           l_smfEnabled),
             "Error from FAPI_ATTR_GET for attribute ATTR_SMF_ENABLED ");

    FAPI_DBG("SMF Status : %s", l_smfEnabled ? "Enabled" : "Disabled" );

    for( auto core : l_coreList )
    {
        FAPI_TRY(fapi2::getScom(i_procTarget, C_CPPM_CPMMR, l_wakeupMode),
                 "Failed To Read CPMMR");

        FAPI_DBG( "Initial CPMMR Value 0x%016llx", l_wakeupMode );

        if( l_smfEnabled )
        {
            //Wakeup in Ultravisor mode
            l_wakeupMode.clearBit( RUN_TIME_WAKEUP_MODE_BIT_POS );
            l_wakeupMode.clearBit( HV_COMPATIBILITY_MODE_BIT_POS );
        }
        else
        {
            //Wakeup in Hypervisor mode
            l_wakeupMode.setBit( RUN_TIME_WAKEUP_MODE_BIT_POS );
            l_wakeupMode.setBit( HV_COMPATIBILITY_MODE_BIT_POS );
        }

        FAPI_TRY(fapi2::putScom(core, C_CPPM_CPMMR, l_wakeupMode),
                 "Failed To Write CPMMR");

        FAPI_DBG( "Final CPMMR Value 0x%016llx", l_wakeupMode );

    }

fapi_try_exit:
    FAPI_INF("< p9_setup_runtime_wakeup_mode" );
    return fapi2::current_err;
}
<commit_msg>UV Support: Fixed target issue in setup runtime wakeup mode HWP.<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_setup_runtime_wakeup_mode.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file   p9_setup_runtime_wakeup_mode.H
/// @brief  describes HWP interface that configures runtime wakeup mode of core.
///
/// *HWP HWP Owner:      Greg Still <stillgs@us.ibm.com>
/// *HWP FW Owner:       Prem S Jha <premjha2@in.ibm.com>
/// *HWP Team:           PM
/// *HWP Level:          2
/// *HWP Consumed by:    Hostboot
//

#include <p9_setup_runtime_wakeup_mode.H>
#include <p9_quad_scom_addresses.H>

enum
{
    RUN_TIME_WAKEUP_MODE_BIT_POS    =   3,
    HV_COMPATIBILITY_MODE_BIT_POS   =   4,
};

fapi2::ReturnCode p9_setup_runtime_wakeup_mode(
    const fapi2::Target < fapi2::TARGET_TYPE_PROC_CHIP>& i_procTarget )
{
    FAPI_INF("> p9_setup_runtime_wakeup_mode" );
    fapi2::buffer<uint64_t> l_wakeupMode;
    uint8_t l_smfEnabled;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    auto l_coreList =
        i_procTarget.getChildren<fapi2::TARGET_TYPE_CORE>(fapi2::TARGET_STATE_FUNCTIONAL);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SMF_ENABLED,
                           FAPI_SYSTEM,
                           l_smfEnabled),
             "Error from FAPI_ATTR_GET for attribute ATTR_SMF_ENABLED ");

    FAPI_DBG("SMF Status : %s", l_smfEnabled ? "Enabled" : "Disabled" );

    for( auto core : l_coreList )
    {
        FAPI_TRY(fapi2::getScom( core, C_CPPM_CPMMR, l_wakeupMode),
                 "Failed To Read CPMMR");

        FAPI_DBG( "Initial CPMMR Value 0x%016llx", l_wakeupMode );

        if( l_smfEnabled )
        {
            //Wakeup in Ultravisor mode
            l_wakeupMode.clearBit( RUN_TIME_WAKEUP_MODE_BIT_POS );
            l_wakeupMode.clearBit( HV_COMPATIBILITY_MODE_BIT_POS );
        }
        else
        {
            //Wakeup in Hypervisor mode
            l_wakeupMode.setBit( RUN_TIME_WAKEUP_MODE_BIT_POS );
            l_wakeupMode.setBit( HV_COMPATIBILITY_MODE_BIT_POS );
        }

        FAPI_TRY(fapi2::putScom(core, C_CPPM_CPMMR, l_wakeupMode),
                 "Failed To Write CPMMR");

        FAPI_DBG( "Final CPMMR Value 0x%016llx", l_wakeupMode );

    }

fapi_try_exit:
    FAPI_INF("< p9_setup_runtime_wakeup_mode" );
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>#pragma once
#include "detect_type.hpp"
#include "lubee/meta/enable_if.hpp"
#include "lubee/none.hpp"
#include "argholder.hpp"
#include <utility>
#include "none.hpp"

namespace spi {
	template <class... Ts>
	auto construct(Ts&&... ts) {
		return ArgHolder<decltype(ts)...>(std::forward<Ts>(ts)...);
	}
	template <class P>
	using IsRP = std::integral_constant<bool, std::is_reference<P>{} || std::is_pointer<P>{}>;
	namespace opt_tmp {
		template <class T>
		struct alignas(alignof(T)) Buffer {
			uint8_t		_data[sizeof(T)];

			Buffer() = default;
			template <class T2>
			Buffer(T2&& t) {
				new(ptr()) T(std::forward<T2>(t));
			}

			T* ptr() noexcept {
				// Debug時は中身が有効かチェック
				#ifdef DEBUG
				#endif
				return reinterpret_cast<T*>(_data);
			}
			const T* ptr() const noexcept {
				// Debug時は中身が有効かチェック
				#ifdef DEBUG
				#endif
				return reinterpret_cast<const T*>(_data);
			}
			T& get() noexcept {
				return *ptr();
			}
			const T& get() const noexcept {
				return *ptr();
			}
			template <class... Ts>
			void ctor(Ts&&... ts) {
				new(ptr()) T(std::forward<Ts>(ts)...);
			}
			void dtor() noexcept {
				ptr()->~T();
			}
			#define NOEXCEPT_WHEN_RAW(t) noexcept(noexcept(IsRP<t>{}))
			template <class T2>
			Buffer& operator = (T2&& t) NOEXCEPT_WHEN_RAW(T2) {
				get() = std::forward<T2>(t);
				return *this;
			}
			#undef NOEXCEPT_WHEN_RAW
			template <class Ar, class T2>
			friend void serialize(Ar&, Buffer<T2>&);
		};
		template <class T>
		struct Buffer<T&> {
			T*	_data;

			Buffer() = default;
			Buffer(T& t) noexcept: _data(&t) {}
			T* ptr() noexcept {
				return _data;
			}
			const T* ptr() const noexcept {
				return _data;
			}
			T& get() noexcept {
				return *ptr();
			}
			const T& get() const noexcept {
				return *ptr();
			}
			void ctor() noexcept {}
			void ctor(T& t) noexcept{
				_data = &t;
			}
			void dtor() noexcept {}
			Buffer& operator = (T& t) noexcept {
				_data = &t;
				return *this;
			}
			template <class Ar, class T2>
			friend void serialize(Ar&, opt_tmp::Buffer<T2&>&);
		};
		template <class T>
		struct Buffer<T*> {
			T*	_data;

			Buffer() = default;
			Buffer(T* t) noexcept: _data(t) {}
			T* ptr() noexcept {
				return _data;
			}
			const T* ptr() const noexcept {
				return _data;
			}
			T*& get() noexcept {
				return _data;
			}
			T* const& get() const noexcept {
				return _data;
			}
			void ctor() noexcept {}
			void ctor(T* t) noexcept {
				_data = t;
			}
			void dtor() noexcept {}
			Buffer& operator = (T* t) noexcept {
				_data = t;
				return *this;
			}
			template <class Ar, class T2>
			friend void serialize(Ar&, opt_tmp::Buffer<T2*>&);
		};
	}

	template <class T>
	class Optional {
		private:
			using value_t = T;
			constexpr static bool Is_RP = IsRP<T>{};
			using Buffer = opt_tmp::Buffer<T>;
			Buffer	_buffer;
			bool	_bInit;

			void _force_release() noexcept {
				D_Assert0(_bInit);
				_buffer.dtor();
				_bInit = false;
			}
			void _release() noexcept {
				if(_bInit)
					_force_release();
			}
			value_t&& _takeOut() && noexcept {
				return std::move(get());
			}
			const value_t& _takeOut() const& noexcept {
				return get();
			}
			constexpr bool isRvalue() && noexcept {
				return true;
			}
			constexpr bool isRvalue() const& noexcept {
				return false;
			}

		public:
			const static struct _AsInitialized{} AsInitialized;
			//! コンストラクタは呼ばないが初期化された物として扱う
			/*! ユーザーが自分でコンストラクタを呼ばないとエラーになる */
			Optional(_AsInitialized) noexcept: _bInit(true) {}

			Optional(const Optional& opt):
				_bInit(opt._bInit)
			{
				if(_bInit) {
					_buffer.ctor(opt._buffer.get());
				}
			}
			Optional(Optional&& opt) noexcept:
				_bInit(opt._bInit)
			{
				if(_bInit) {
					_buffer.ctor(std::move(opt)._takeOut());
					opt._bInit = false;
				}
			}
			template <class T2, ENABLE_IF(!(is_optional<std::decay_t<T2>>{}))>
			Optional(T2&& v) noexcept(!IsRP<T2>{}):
				_buffer(std::forward<T2>(v)),
				_bInit(true)
			{}
			template <class T2, ENABLE_IF((is_optional<std::decay_t<T2>>{}))>
			Optional(T2&& v) noexcept(!IsRP<T2>{}):
				_bInit(v._bInit)
			{
				if(_bInit) {
					const bool bR = std::forward<T2>(v).isRvalue();
					_buffer.ctor(std::forward<T2>(v)._takeOut());
					if(bR)
						v._bInit = false;
				}
			}
			//! デフォルト初期化: 中身は無効
			Optional() noexcept: _bInit(false) {}
			//! none_tを渡して初期化するとデフォルトと同じ挙動
			Optional(none_t) noexcept: Optional() {}
			~Optional() {
				_release();
			}
			decltype(auto) get() & noexcept {
				return _buffer.get();
			}
			decltype(auto) get() const& noexcept {
				return _buffer.get();
			}
			decltype(auto) get() && noexcept {
				return std::move(_buffer.get());
			}
			decltype(auto) operator * () & noexcept { return get(); }
			decltype(auto) operator * () const& noexcept { return get(); }
			decltype(auto) operator * () && noexcept { return std::move(get()); }

			explicit operator bool () const noexcept {
				return _bInit;
			}
			decltype(auto) operator -> () noexcept {
				return _buffer.ptr();
			}
			decltype(auto) operator -> () const noexcept {
				return _buffer.ptr();
			}
			bool operator == (const Optional& t) const noexcept {
				const bool b = _bInit;
				if(b == t._bInit) {
					if(b)
						return get() == t.get();
					return true;
				}
				return false;
			}
			bool operator != (const Optional& t) const noexcept {
				return !(this->operator == (t));
			}
			Optional& operator = (none_t) noexcept {
				_release();
				return *this;
			}
			template <class T2>
			bool construct(std::true_type, T2&& t) {
				_buffer.ctor(std::forward<T2>(t));
				return true;
			}
			template <class T2>
			bool construct(std::false_type, T2&&) {
				_buffer.ctor();
				return false;
			}
			template <
				class T2,
				ENABLE_IF(!(is_optional<std::decay_t<T2>>{}))
			>
			Optional& operator = (T2&& t) {
				if(!_bInit) {
					_bInit = true;
					using CanConstruct = std::is_constructible<value_t, decltype(std::forward<T2>(t))>;
					if(construct(CanConstruct{}, std::forward<T2>(t)))
						return *this;
				}
				_buffer = std::forward<T2>(t);
				return *this;
			}
			template <class... Ts>
			Optional& operator = (ArgHolder<Ts...>&& ah) {
				if(_bInit)
					_release();
				const auto fn = [&buff = _buffer](auto&&... ts) {
					buff.ctor(std::forward<decltype(ts)>(ts)...);
				};
				ah.inorder(fn);
				_bInit = true;
				return *this;
			}
			template <class T2, ENABLE_IF((is_optional<std::decay_t<T2>>{}))>
			Optional& operator = (T2&& t) noexcept(Is_RP) {
				if(!t)
					_release();
				else {
					_bInit = true;
					_buffer = std::forward<T2>(t).get();
				}
				return *this;
			}
			template <class Ar, class T2>
			friend void load(Ar&, Optional<T2>&);
			template <class Ar, class T2>
			friend void save(Ar&, const Optional<T2>&);
	};
	template <class T>
	const typename Optional<T>::_AsInitialized Optional<T>::AsInitialized{};
}
<commit_msg>Optional: リファクタリング<commit_after>#pragma once
#include "detect_type.hpp"
#include "lubee/meta/enable_if.hpp"
#include "lubee/none.hpp"
#include "argholder.hpp"
#include <utility>
#include "none.hpp"

namespace spi {
	template <class... Ts>
	auto construct(Ts&&... ts) {
		return ArgHolder<decltype(ts)...>(std::forward<Ts>(ts)...);
	}
	template <class P>
	using IsRP = std::integral_constant<bool, std::is_reference<P>{} || std::is_pointer<P>{}>;
	namespace opt_tmp {
		template <class T>
		struct alignas(alignof(T)) Buffer {
			uint8_t		_data[sizeof(T)];

			Buffer() = default;
			template <class T2>
			Buffer(T2&& t) {
				new(ptr()) T(std::forward<T2>(t));
			}

			T* ptr() noexcept {
				// Debug時は中身が有効かチェック
				#ifdef DEBUG
				#endif
				return reinterpret_cast<T*>(_data);
			}
			const T* ptr() const noexcept {
				// Debug時は中身が有効かチェック
				#ifdef DEBUG
				#endif
				return reinterpret_cast<const T*>(_data);
			}
			T& get() noexcept {
				return *ptr();
			}
			const T& get() const noexcept {
				return *ptr();
			}
			template <class... Ts>
			void ctor(Ts&&... ts) noexcept(noexcept(new T(std::forward<Ts>(ts)...))) {
				new(ptr()) T(std::forward<Ts>(ts)...);
			}
			void dtor() noexcept {
				ptr()->~T();
			}
			#define NOEXCEPT_WHEN_RAW(t) noexcept(noexcept(IsRP<t>{}))
			template <class T2>
			Buffer& operator = (T2&& t) NOEXCEPT_WHEN_RAW(T2) {
				get() = std::forward<T2>(t);
				return *this;
			}
			#undef NOEXCEPT_WHEN_RAW
			template <class Ar, class T2>
			friend void serialize(Ar&, Buffer<T2>&);
		};
		template <class T>
		struct Buffer<T&> {
			T*	_data;

			Buffer() = default;
			Buffer(T& t) noexcept: _data(&t) {}
			T* ptr() noexcept {
				return _data;
			}
			const T* ptr() const noexcept {
				return _data;
			}
			T& get() noexcept {
				return *ptr();
			}
			const T& get() const noexcept {
				return *ptr();
			}
			void ctor() noexcept {}
			void ctor(T& t) noexcept{
				_data = &t;
			}
			void dtor() noexcept {}
			Buffer& operator = (T& t) noexcept {
				_data = &t;
				return *this;
			}
			template <class Ar, class T2>
			friend void serialize(Ar&, opt_tmp::Buffer<T2&>&);
		};
		template <class T>
		struct Buffer<T*> {
			T*	_data;

			Buffer() = default;
			Buffer(T* t) noexcept: _data(t) {}
			T* ptr() noexcept {
				return _data;
			}
			const T* ptr() const noexcept {
				return _data;
			}
			T*& get() noexcept {
				return _data;
			}
			T* const& get() const noexcept {
				return _data;
			}
			void ctor() noexcept {}
			void ctor(T* t) noexcept {
				_data = t;
			}
			void dtor() noexcept {}
			Buffer& operator = (T* t) noexcept {
				_data = t;
				return *this;
			}
			template <class Ar, class T2>
			friend void serialize(Ar&, opt_tmp::Buffer<T2*>&);
		};
	}

	template <class T>
	class Optional {
		private:
			using value_t = T;
			constexpr static bool Is_RP = IsRP<T>{};
			using Buffer = opt_tmp::Buffer<T>;
			Buffer	_buffer;
			bool	_bInit;

			void _force_release() noexcept {
				D_Assert0(_bInit);
				_buffer.dtor();
				_bInit = false;
			}
			void _release() noexcept {
				if(_bInit)
					_force_release();
			}
			constexpr bool isRvalue() && noexcept {
				return true;
			}
			constexpr bool isRvalue() const& noexcept {
				return false;
			}
			template <class T2>
			bool _construct(std::true_type, T2&& t) {
				_buffer.ctor(std::forward<T2>(t));
				return true;
			}
			template <class T2>
			bool _construct(std::false_type, T2&&) {
				_buffer.ctor();
				return false;
			}

		public:
			const static struct _AsInitialized{} AsInitialized;
			//! コンストラクタは呼ばないが初期化された物として扱う
			/*! ユーザーが自分でコンストラクタを呼ばないとエラーになる */
			Optional(_AsInitialized) noexcept:
				_bInit(true)
			{}

			Optional(const Optional& opt):
				_bInit(opt._bInit)
			{
				if(_bInit) {
					_buffer.ctor(opt._buffer.get());
				}
			}
			Optional(Optional&& opt) noexcept:
				_bInit(opt._bInit)
			{
				if(_bInit) {
					_buffer.ctor(std::move(opt).get());
					opt._bInit = false;
				}
			}
			template <class T2, ENABLE_IF(!(is_optional<std::decay_t<T2>>{}))>
			Optional(T2&& v) noexcept(noexcept(Buffer(std::forward<T2>(v)))):
				_buffer(std::forward<T2>(v)),
				_bInit(true)
			{}
			template <class T2, ENABLE_IF((is_optional<std::decay_t<T2>>{}))>
			Optional(T2&& v) noexcept(noexcept(std::declval<Buffer>().ctor(std::forward<T2>(v).get()))):
				_bInit(v._bInit)
			{
				if(_bInit) {
					const bool bR = std::forward<T2>(v).isRvalue();
					_buffer.ctor(std::forward<T2>(v).get());
					if(bR)
						v._bInit = false;
				}
			}
			//! デフォルト初期化: 中身は無効
			Optional() noexcept:
				_bInit(false)
			{}
			//! none_tを渡して初期化するとデフォルトと同じ挙動
			Optional(none_t) noexcept:
				Optional()
			{}
			~Optional() {
				_release();
			}
			decltype(auto) get() & noexcept {
				return _buffer.get();
			}
			decltype(auto) get() const& noexcept {
				return _buffer.get();
			}
			decltype(auto) get() && noexcept {
				return std::move(_buffer.get());
			}
			decltype(auto) operator * () & noexcept {
				return get();
			}
			decltype(auto) operator * () const& noexcept {
				return get();
			}
			decltype(auto) operator * () && noexcept {
				return std::move(get());
			}
			explicit operator bool () const noexcept {
				return _bInit;
			}
			decltype(auto) operator -> () noexcept {
				return _buffer.ptr();
			}
			decltype(auto) operator -> () const noexcept {
				return _buffer.ptr();
			}
			bool operator == (const Optional& t) const noexcept {
				const bool b = _bInit;
				if(b == t._bInit) {
					if(b)
						return get() == t.get();
					return true;
				}
				return false;
			}
			bool operator != (const Optional& t) const noexcept {
				return !(this->operator == (t));
			}
			Optional& operator = (none_t) noexcept {
				_release();
				return *this;
			}
			template <
				class T2,
				ENABLE_IF(!(is_optional<std::decay_t<T2>>{}))
			>
			Optional& operator = (T2&& t) {
				if(!_bInit) {
					_bInit = true;
					using CanConstruct = std::is_constructible<value_t, decltype(std::forward<T2>(t))>;
					if(_construct(CanConstruct{}, std::forward<T2>(t)))
						return *this;
				}
				_buffer = std::forward<T2>(t);
				return *this;
			}
			template <class... Ts>
			Optional& operator = (ArgHolder<Ts...>&& ah) {
				if(_bInit)
					_release();
				const auto fn = [&buff = _buffer](auto&&... ts) {
					buff.ctor(std::forward<decltype(ts)>(ts)...);
				};
				ah.inorder(fn);
				_bInit = true;
				return *this;
			}
			template <class T2, ENABLE_IF((is_optional<std::decay_t<T2>>{}))>
			Optional& operator = (T2&& t) noexcept(Is_RP) {
				if(!t)
					_release();
				else {
					_bInit = true;
					_buffer = std::forward<T2>(t).get();
				}
				return *this;
			}
			template <class Ar, class T2>
			friend void load(Ar&, Optional<T2>&);
			template <class Ar, class T2>
			friend void save(Ar&, const Optional<T2>&);
	};
	template <class T>
	const typename Optional<T>::_AsInitialized Optional<T>::AsInitialized{};
}
<|endoftext|>