<commit_before>/*
 * Copyright (c) 2003-2009, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "entry.h"
#include "journal.h"
#include "format.h"
#include "session.h"
#include "report.h"

namespace ledger {

entry_base_t::entry_base_t(const entry_base_t& e)
  : item_t(), journal(NULL)
{
  TRACE_CTOR(entry_base_t, "copy");
#if 0
  xacts.insert(xacts.end(), e.xacts.begin(), e.xacts.end());
#endif
}

entry_base_t::~entry_base_t()
{
  TRACE_DTOR(entry_base_t);

  foreach (xact_t * xact, xacts) {
    // If the transaction is a temporary, it will be destructed when the
    // temporary is.  If it's from a binary cache, we can safely destruct it
    // but its memory will be deallocated with the cache.
    if (! xact->has_flags(ITEM_TEMP)) {
      if (! xact->has_flags(ITEM_IN_CACHE))
	checked_delete(xact);
      else
	xact->~xact_t();
    }
  }
}

item_t::state_t entry_base_t::state() const
{
  bool	  first	 = true;
  state_t result = UNCLEARED;

  foreach (xact_t * xact, xacts) {
    if ((result == UNCLEARED && xact->_state != UNCLEARED) ||
	(result == PENDING   && xact->_state == CLEARED))
      result = xact->_state;
  }

  return result;
}

void entry_base_t::add_xact(xact_t * xact)
{
  xacts.push_back(xact);
}

bool entry_base_t::remove_xact(xact_t * xact)
{
  xacts.remove(xact);
  return true;
}

bool entry_base_t::finalize()
{
  // Scan through and compute the total balance for the entry.  This is used
  // for auto-calculating the value of entries with no cost, and the per-unit
  // price of unpriced commodities.

  // (let ((balance 0)
  //       null-xact)

  value_t  balance;
  xact_t * null_xact = NULL;

  foreach (xact_t * xact, xacts) {
    if (xact->must_balance()) {
      amount_t& p(xact->cost ? *xact->cost : xact->amount);
      DEBUG("entry.finalize", "xact must balance = " << p);
      if (! p.is_null()) {
	if (p.keep_precision()) {
	  amount_t temp(p);
	  // If the amount was a cost, it very likely has the "keep_precision"
	  // flag set, meaning commodity display precision is ignored when
	  // displaying the amount.  We never want this set for the balance,
	  // so we must clear the flag in a temporary to avoid it propagating
	  // into the balance.
	  temp.set_keep_precision(false);
	  add_or_set_value(balance, temp);
	} else {
	  add_or_set_value(balance, p);
	}
      } else {
	if (null_xact)
	  throw_(std::logic_error,
		 "Only one xact with null amount allowed per entry");
	else
	  null_xact = xact;
      }
    }
  }
  assert(balance.valid());

  DEBUG("entry.finalize", "initial balance = " << balance);

  // If there is only one xact, balance against the default account if
  // one has been set.

  if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) {
    // jww (2008-07-24): Need to make the rest of the code aware of what to do
    // when it sees a generated xact.
    null_xact = new xact_t(journal->basket, ITEM_GENERATED);
    null_xact->_state = (*xacts.begin())->_state;
    add_xact(null_xact);
  }

  if (null_xact != NULL) {
    // If one xact has no value at all, its value will become the
    // inverse of the rest.  If multiple commodities are involved, multiple
    // xacts are generated to balance them all.

    if (balance.is_balance()) {
      bool first = true;
      const balance_t& bal(balance.as_balance());
      foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) {
	if (first) {
	  null_xact->amount = pair.second.negate();
	  first = false;
	} else {
	  add_xact(new xact_t(null_xact->account, pair.second.negate(),
			      ITEM_GENERATED));
	}
      }
    }
    else if (balance.is_amount()) {
      null_xact->amount = balance.as_amount().negate();
      null_xact->add_flags(XACT_CALCULATED);
    }
    else if (! balance.is_null() && ! balance.is_realzero()) {
      throw_(balance_error, "Entry does not balance");
    }
    balance = NULL_VALUE;

  }
  else if (balance.is_balance() &&
	   balance.as_balance().amounts.size() == 2) {
    // When an entry involves two different commodities (regardless of how
    // many xacts there are) determine the conversion ratio by dividing
    // the total value of one commodity by the total value of the other.  This
    // establishes the per-unit cost for this xact for both
    // commodities.

    const balance_t& bal(balance.as_balance());

    balance_t::amounts_map::const_iterator a = bal.amounts.begin();

    const amount_t& x((*a++).second);
    const amount_t& y((*a++).second);

    if (! y.is_realzero()) {
      amount_t per_unit_cost = (x / y).abs();

      commodity_t& comm(x.commodity());

      foreach (xact_t * xact, xacts) {
	const amount_t& amt(xact->amount);

	if (! (xact->cost || ! xact->must_balance() ||
	       amt.commodity() == comm)) {
	  balance -= amt;
	  xact->cost = per_unit_cost * amt;
	  balance += *xact->cost;
	}

      }
    }

    DEBUG("entry.finalize", "resolved balance = " << balance);
  }

  // Now that the xact list has its final form, calculate the balance
  // once more in terms of total cost, accounting for any possible gain/loss
  // amounts.

  foreach (xact_t * xact, xacts) {
    if (xact->cost) {
      if (xact->amount.commodity() == xact->cost->commodity())
	throw_(balance_error, "Transaction's cost must be of a different commodity");

      commodity_t::cost_breakdown_t breakdown =
	commodity_t::exchange(xact->amount, *xact->cost);

      if (xact->amount.is_annotated())
	add_or_set_value(balance, breakdown.basis_cost - breakdown.final_cost);
      else
	xact->amount = breakdown.amount;
    }
  }

  DEBUG("entry.finalize", "final balance = " << balance);

  if (! balance.is_null() && ! balance.is_zero()) {
#if 0
    add_error_context(entry_context(*this));
#endif
    add_error_context("Unbalanced remainder is: ");
    add_error_context(value_context(balance.unrounded()));
    throw_(balance_error, "Entry does not balance");
  }

  // Add the final calculated totals each to their related account

  if (dynamic_cast<entry_t *>(this)) {
    bool all_null = true;
    foreach (xact_t * xact, xacts) {
      if (! xact->amount.is_null()) {
	all_null = false;

	// jww (2008-08-09): For now, this feature only works for
	// non-specific commodities.
	add_or_set_value(xact->account->xdata().value, xact->amount);

	DEBUG("entry.finalize.totals",
	      "Total for " << xact->account->fullname() << " + "
	      << xact->amount.strip_annotations() << ": "
	      << xact->account->xdata().value.strip_annotations());
      }
    }
    if (all_null)
      return false;		// ignore this entry completely
  }

  return true;
}

entry_t::entry_t(const entry_t& e)
  : entry_base_t(e), code(e.code), payee(e.payee)
{
  TRACE_CTOR(entry_t, "copy");
#if 0
  foreach (xact_t * xact, xacts)
    xact->entry = this;
#endif
}

void entry_t::add_xact(xact_t * xact)
{
  xact->entry = this;
  entry_base_t::add_xact(xact);
}

namespace {
  value_t get_code(entry_t& entry) {
    if (entry.code)
      return string_value(*entry.code);
    else
      return string_value(empty_string);
  }

  value_t get_payee(entry_t& entry) {
    return string_value(entry.payee);
  }

  template <value_t (*Func)(entry_t&)>
  value_t get_wrapper(call_scope_t& scope) {
    return (*Func)(find_scope<entry_t>(scope));
  }
}

expr_t::ptr_op_t entry_t::lookup(const string& name)
{
  switch (name[0]) {
  case 'c':
    if (name == "code")
      return WRAP_FUNCTOR(get_wrapper<&get_code>);
    break;

  case 'p':
    if (name[1] == '\0' || name == "payee")
      return WRAP_FUNCTOR(get_wrapper<&get_payee>);
    break;
  }

  return item_t::lookup(name);
}

bool entry_t::valid() const
{
  if (! _date || ! journal) {
    DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
    return false;
  }

  foreach (xact_t * xact, xacts)
    if (xact->entry != this || ! xact->valid()) {
      DEBUG("ledger.validate", "entry_t: xact not valid");
      return false;
    }

  return true;
}

#if 0
void entry_context::describe(std::ostream& out) const throw()
{
  if (! desc.empty())
    out << desc << std::endl;

  print_entry(out, entry, "  ");
}
#endif

void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
{
  xacts_list initial_xacts(entry.xacts.begin(),
				  entry.xacts.end());

  foreach (xact_t * initial_xact, initial_xacts) {
    if (predicate(*initial_xact)) {
      foreach (xact_t * xact, xacts) {
	amount_t amt;
	assert(xact->amount);
	if (! xact->amount.commodity()) {
	  if (! post)
	    continue;
	  assert(initial_xact->amount);
	  amt = initial_xact->amount * xact->amount;
	} else {
	  if (post)
	    continue;
	  amt = xact->amount;
	}

	IF_DEBUG("entry.extend") {
	  DEBUG("entry.extend",
		"Initial xact on line " << initial_xact->beg_line << ": "
		<< "amount " << initial_xact->amount << " (precision "
		<< initial_xact->amount.precision() << ")");

	  if (initial_xact->amount.keep_precision())
	    DEBUG("entry.extend", "  precision is kept");

	  DEBUG("entry.extend",
		"Transaction on line " << xact->beg_line << ": "
		<< "amount " << xact->amount << ", amt " << amt
		<< " (precision " << xact->amount.precision()
		<< " != " << amt.precision() << ")");

	  if (xact->amount.keep_precision())
	    DEBUG("entry.extend", "  precision is kept");
	  if (amt.keep_precision())
	    DEBUG("entry.extend", "  amt precision is kept");
	}

	account_t * account  = xact->account;
	string fullname = account->fullname();
	assert(! fullname.empty());
	if (fullname == "$account" || fullname == "@account")
	  account = initial_xact->account;

	// Copy over details so that the resulting xact is a mirror of
	// the automated entry's one.
	xact_t * new_xact = new xact_t(account, amt);
	new_xact->copy_details(*xact);
	new_xact->add_flags(XACT_AUTO);

	entry.add_xact(new_xact);
      }
    }
  }
}

void extend_entry_base(journal_t * journal, entry_base_t& base, bool post)
{
  foreach (auto_entry_t * entry, journal->auto_entries)
    entry->extend_entry(base, post);
}

} // namespace ledger
<commit_msg>Fixed some entry balancing problems relating to the new rational code.<commit_after>/*
 * Copyright (c) 2003-2009, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "entry.h"
#include "journal.h"
#include "format.h"
#include "session.h"
#include "report.h"

namespace ledger {

entry_base_t::entry_base_t(const entry_base_t& e)
  : item_t(), journal(NULL)
{
  TRACE_CTOR(entry_base_t, "copy");
#if 0
  xacts.insert(xacts.end(), e.xacts.begin(), e.xacts.end());
#endif
}

entry_base_t::~entry_base_t()
{
  TRACE_DTOR(entry_base_t);

  foreach (xact_t * xact, xacts) {
    // If the transaction is a temporary, it will be destructed when the
    // temporary is.  If it's from a binary cache, we can safely destruct it
    // but its memory will be deallocated with the cache.
    if (! xact->has_flags(ITEM_TEMP)) {
      if (! xact->has_flags(ITEM_IN_CACHE))
	checked_delete(xact);
      else
	xact->~xact_t();
    }
  }
}

item_t::state_t entry_base_t::state() const
{
  bool	  first	 = true;
  state_t result = UNCLEARED;

  foreach (xact_t * xact, xacts) {
    if ((result == UNCLEARED && xact->_state != UNCLEARED) ||
	(result == PENDING   && xact->_state == CLEARED))
      result = xact->_state;
  }

  return result;
}

void entry_base_t::add_xact(xact_t * xact)
{
  xacts.push_back(xact);
}

bool entry_base_t::remove_xact(xact_t * xact)
{
  xacts.remove(xact);
  return true;
}

bool entry_base_t::finalize()
{
  // Scan through and compute the total balance for the entry.  This is used
  // for auto-calculating the value of entries with no cost, and the per-unit
  // price of unpriced commodities.

  // (let ((balance 0)
  //       null-xact)

  value_t  balance;
  xact_t * null_xact = NULL;

  foreach (xact_t * xact, xacts) {
    if (xact->must_balance()) {
      amount_t& p(xact->cost ? *xact->cost : xact->amount);
      DEBUG("entry.finalize", "xact must balance = " << p);
      if (! p.is_null()) {
	if (p.keep_precision()) {
	  // If the amount was a cost, it very likely has the "keep_precision"
	  // flag set, meaning commodity display precision is ignored when
	  // displaying the amount.  We never want this set for the balance,
	  // so we must clear the flag in a temporary to avoid it propagating
	  // into the balance.
	  add_or_set_value(balance, p.rounded());
	} else {
	  add_or_set_value(balance, p);
	}
      } else {
	if (null_xact)
	  throw_(std::logic_error,
		 "Only one xact with null amount allowed per entry");
	else
	  null_xact = xact;
      }
    }
  }
  assert(balance.valid());

  DEBUG("entry.finalize", "initial balance = " << balance);

  // If there is only one xact, balance against the default account if
  // one has been set.

  if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) {
    // jww (2008-07-24): Need to make the rest of the code aware of what to do
    // when it sees a generated xact.
    null_xact = new xact_t(journal->basket, ITEM_GENERATED);
    null_xact->_state = (*xacts.begin())->_state;
    add_xact(null_xact);
  }

  if (null_xact != NULL) {
    // If one xact has no value at all, its value will become the
    // inverse of the rest.  If multiple commodities are involved, multiple
    // xacts are generated to balance them all.

    if (balance.is_balance()) {
      bool first = true;
      const balance_t& bal(balance.as_balance());
      foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) {
	if (first) {
	  null_xact->amount = pair.second.negate();
	  first = false;
	} else {
	  add_xact(new xact_t(null_xact->account, pair.second.negate(),
			      ITEM_GENERATED));
	}
      }
    }
    else if (balance.is_amount()) {
      null_xact->amount = balance.as_amount().negate();
      null_xact->add_flags(XACT_CALCULATED);
    }
    else if (! balance.is_null() && ! balance.is_realzero()) {
      throw_(balance_error, "Entry does not balance");
    }
    balance = NULL_VALUE;

  }
  else if (balance.is_balance() &&
	   balance.as_balance().amounts.size() == 2) {
    // When an entry involves two different commodities (regardless of how
    // many xacts there are) determine the conversion ratio by dividing
    // the total value of one commodity by the total value of the other.  This
    // establishes the per-unit cost for this xact for both
    // commodities.

    const balance_t& bal(balance.as_balance());

    balance_t::amounts_map::const_iterator a = bal.amounts.begin();

    const amount_t& x((*a++).second);
    const amount_t& y((*a++).second);

    if (! y.is_realzero()) {
      amount_t per_unit_cost = (x / y).abs();

      commodity_t& comm(x.commodity());

      foreach (xact_t * xact, xacts) {
	const amount_t& amt(xact->amount);

	if (! (xact->cost || ! xact->must_balance() ||
	       amt.commodity() == comm)) {
	  balance -= amt;
	  xact->cost = per_unit_cost * amt;
	  balance += *xact->cost;
	}

      }
    }

    DEBUG("entry.finalize", "resolved balance = " << balance);
  }

  // Now that the xact list has its final form, calculate the balance
  // once more in terms of total cost, accounting for any possible gain/loss
  // amounts.

  foreach (xact_t * xact, xacts) {
    if (xact->cost) {
      if (xact->amount.commodity() == xact->cost->commodity())
	throw_(balance_error, "Transaction's cost must be of a different commodity");

      commodity_t::cost_breakdown_t breakdown =
	commodity_t::exchange(xact->amount, *xact->cost);

      if (xact->amount.is_annotated())
	add_or_set_value(balance, (breakdown.basis_cost -
				   breakdown.final_cost).rounded());
      else
	xact->amount = breakdown.amount;
    }
  }

  DEBUG("entry.finalize", "final balance = " << balance);

  if (! balance.is_null() && ! balance.is_zero()) {
#if 0
    add_error_context(entry_context(*this));
#endif
    add_error_context("Unbalanced remainder is: ");
    add_error_context(value_context(balance));
    throw_(balance_error, "Entry does not balance");
  }

  // Add the final calculated totals each to their related account

  if (dynamic_cast<entry_t *>(this)) {
    bool all_null = true;
    foreach (xact_t * xact, xacts) {
      if (! xact->amount.is_null()) {
	all_null = false;

	// jww (2008-08-09): For now, this feature only works for
	// non-specific commodities.
	add_or_set_value(xact->account->xdata().value, xact->amount);

	DEBUG("entry.finalize.totals",
	      "Total for " << xact->account->fullname() << " + "
	      << xact->amount.strip_annotations() << ": "
	      << xact->account->xdata().value.strip_annotations());
      }
    }
    if (all_null)
      return false;		// ignore this entry completely
  }

  return true;
}

entry_t::entry_t(const entry_t& e)
  : entry_base_t(e), code(e.code), payee(e.payee)
{
  TRACE_CTOR(entry_t, "copy");
#if 0
  foreach (xact_t * xact, xacts)
    xact->entry = this;
#endif
}

void entry_t::add_xact(xact_t * xact)
{
  xact->entry = this;
  entry_base_t::add_xact(xact);
}

namespace {
  value_t get_code(entry_t& entry) {
    if (entry.code)
      return string_value(*entry.code);
    else
      return string_value(empty_string);
  }

  value_t get_payee(entry_t& entry) {
    return string_value(entry.payee);
  }

  template <value_t (*Func)(entry_t&)>
  value_t get_wrapper(call_scope_t& scope) {
    return (*Func)(find_scope<entry_t>(scope));
  }
}

expr_t::ptr_op_t entry_t::lookup(const string& name)
{
  switch (name[0]) {
  case 'c':
    if (name == "code")
      return WRAP_FUNCTOR(get_wrapper<&get_code>);
    break;

  case 'p':
    if (name[1] == '\0' || name == "payee")
      return WRAP_FUNCTOR(get_wrapper<&get_payee>);
    break;
  }

  return item_t::lookup(name);
}

bool entry_t::valid() const
{
  if (! _date || ! journal) {
    DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
    return false;
  }

  foreach (xact_t * xact, xacts)
    if (xact->entry != this || ! xact->valid()) {
      DEBUG("ledger.validate", "entry_t: xact not valid");
      return false;
    }

  return true;
}

#if 0
void entry_context::describe(std::ostream& out) const throw()
{
  if (! desc.empty())
    out << desc << std::endl;

  print_entry(out, entry, "  ");
}
#endif

void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
{
  xacts_list initial_xacts(entry.xacts.begin(),
				  entry.xacts.end());

  foreach (xact_t * initial_xact, initial_xacts) {
    if (predicate(*initial_xact)) {
      foreach (xact_t * xact, xacts) {
	amount_t amt;
	assert(xact->amount);
	if (! xact->amount.commodity()) {
	  if (! post)
	    continue;
	  assert(initial_xact->amount);
	  amt = initial_xact->amount * xact->amount;
	} else {
	  if (post)
	    continue;
	  amt = xact->amount;
	}

	IF_DEBUG("entry.extend") {
	  DEBUG("entry.extend",
		"Initial xact on line " << initial_xact->beg_line << ": "
		<< "amount " << initial_xact->amount << " (precision "
		<< initial_xact->amount.precision() << ")");

	  if (initial_xact->amount.keep_precision())
	    DEBUG("entry.extend", "  precision is kept");

	  DEBUG("entry.extend",
		"Transaction on line " << xact->beg_line << ": "
		<< "amount " << xact->amount << ", amt " << amt
		<< " (precision " << xact->amount.precision()
		<< " != " << amt.precision() << ")");

	  if (xact->amount.keep_precision())
	    DEBUG("entry.extend", "  precision is kept");
	  if (amt.keep_precision())
	    DEBUG("entry.extend", "  amt precision is kept");
	}

	account_t * account  = xact->account;
	string fullname = account->fullname();
	assert(! fullname.empty());
	if (fullname == "$account" || fullname == "@account")
	  account = initial_xact->account;

	// Copy over details so that the resulting xact is a mirror of
	// the automated entry's one.
	xact_t * new_xact = new xact_t(account, amt);
	new_xact->copy_details(*xact);
	new_xact->add_flags(XACT_AUTO);

	entry.add_xact(new_xact);
      }
    }
  }
}

void extend_entry_base(journal_t * journal, entry_base_t& base, bool post)
{
  foreach (auto_entry_t * entry, journal->auto_entries)
    entry->extend_entry(base, post);
}

} // namespace ledger
<|endoftext|>


<commit_before>#include "Optimiser.h"
#include "Hildreth.h"

using namespace Moses;
using namespace std;

namespace Mira {

void MiraOptimiser::updateWeights(ScoreComponentCollection& currWeights,
		const vector< vector<ScoreComponentCollection> >& featureValues,
		const vector< vector<float> >& losses,
		const ScoreComponentCollection& oracleFeatureValues) {

	if (m_hildreth) {
		size_t numberOfViolatedConstraints = 0;
		vector< ScoreComponentCollection> featureValueDiffs;
		vector< float> lossMarginDistances;
		for (size_t i = 0; i < featureValues.size(); ++i) {
			for (size_t j = 0; j < featureValues[i].size(); ++j) {
				// check if optimisation criterion is violated for one hypothesis and the oracle
				// h(e*) >= h(e_ij) + loss(e_ij)
				// h(e*) - h(e_ij) >= loss(e_ij)
				float modelScoreDiff = featureValues[i][j].InnerProduct(currWeights);
				if (modelScoreDiff < losses[i][j]) {
					cerr << "Constraint violated: " << modelScoreDiff << " < " << losses[i][j] << endl;
					++numberOfViolatedConstraints;
				}
				else {
					cerr << "Constraint satisfied: " << modelScoreDiff << " >= " << losses[i][j] << endl;
				}

				// Objective: 1/2 * ||w' - w||^2 + C * SUM_1_m[ max_1_n (l_ij - Delta_h_ij.w')]
				// To add a constraint for the optimiser for each sentence i and hypothesis j, we need:
				// 1. vector Delta_h_ij of the feature value differences (oracle - hypothesis)
				// 2. loss_ij - difference in model scores (Delta_h_ij.w') (oracle - hypothesis)
				ScoreComponentCollection featureValueDiff = oracleFeatureValues;
				featureValueDiff.MinusEquals(featureValues[i][j]);
				featureValueDiffs.push_back(featureValueDiff);
				float lossMarginDistance = losses[i][j] - modelScoreDiff;
				lossMarginDistances.push_back(lossMarginDistance);
				// TODO: should we only pass violated constraints to the optimiser?
			}
		}

		if (numberOfViolatedConstraints > 0) {
			// run optimisation
			cerr << "Number of violated constraints: " << numberOfViolatedConstraints << endl;
			// TODO: slack
			// compute deltas for all given constraints
			vector< float> deltas = Hildreth::optimise(featureValueDiffs, lossMarginDistances);

			// Update the weight vector according to the deltas and the feature value differences
			// * w' = w' + delta * Dh_ij ---> w' = w' + delta * (h(e*) - h(e_ij))
			for (size_t k = 0; k < featureValueDiffs.size(); ++k) {
				// scale feature value differences with delta
				featureValueDiffs[k].MultiplyEquals(deltas[k]);

				// apply update to weight vector
				currWeights.PlusEquals(featureValueDiffs[k]);
			}
		}
		else {
			cout << "No constraint violated for this batch" << endl;
		}
	}
	else {
		// SMO:
		for (size_t i = 0; i < featureValues.size(); ++i) {
			// initialise alphas for each source (alpha for oracle translation = C, all other alphas = 0)
			vector< float> alphas(featureValues[i].size());
			for (size_t j = 0; j < featureValues[i].size(); ++j) {
				if (j == m_n) {										// TODO: use oracle index
					// oracle
					alphas[j] = m_c;
					//std::cout << "alpha " << j << ": " << alphas[j] << endl;
				}
				else {
					alphas[j] = 0;
					//std::cout << "alpha " << j << ": " << alphas[j] << endl;
				}
			}

			// consider all pairs of hypotheses
			size_t pairs = 0;
			for (size_t j = 0; j < featureValues[i].size(); ++j) {
				for (size_t k = 0; k < featureValues[i].size(); ++k) {
					if (j <= k) {
						++pairs;

						// Compute delta:
						cout << "\nComparing pair" << j << "," << k << endl;
						ScoreComponentCollection featureValueDiffs;
						float delta = computeDelta(currWeights, featureValues[i], j, k, losses[i], alphas, featureValueDiffs);

						// update weight vector:
						if (delta != 0) {
							update(currWeights, featureValueDiffs, delta);
						}
					}
				}
			}

			cout << "number of pairs: " << pairs << endl;
		}
	}
}

/*
 * Compute delta for weight update.
 * As part of this compute feature value differences
 * Dh_ij - Dh_ij' ---> h(e_ij') - h(e_ij)) --> h(hope) - h(fear)
 * which are used in the delta term and in the weight update term.
 */
float MiraOptimiser::computeDelta(ScoreComponentCollection& currWeights,
		const vector< ScoreComponentCollection>& featureValues,
		const size_t indexHope,
		const size_t indexFear,
		const vector< float>& losses,
		vector< float>& alphas,
		ScoreComponentCollection& featureValueDiffs) {

	const ScoreComponentCollection featureValuesHope = featureValues[indexHope];		// hypothesis j'
	const ScoreComponentCollection featureValuesFear = featureValues[indexFear];		// hypothesis j

	// compute delta
	float delta = 0.0;
	float diffOfModelScores = 0.0;		// (Dh_ij - Dh_ij') * w' --->  (h(e_ij') - h(e_ij))) * w' (inner product)
	float squaredNorm = 0.0;			// ||Dh_ij - Dh_ij'||^2  --->  sum over squares of elements of h(e_ij') - h(e_ij)

	featureValueDiffs = featureValuesHope;
	featureValueDiffs.MinusEquals(featureValuesFear);
	cout << "feature value diffs: " << featureValueDiffs << endl;
	squaredNorm = featureValueDiffs.InnerProduct(featureValueDiffs);
	diffOfModelScores = featureValueDiffs.InnerProduct(currWeights);

	if (squaredNorm == 0.0) {
		delta = 0.0;
	}
	else {
		// loss difference used to compute delta: (l_ij - l_ij')  --->  B(e_ij') - B(e_ij)
		// TODO: simplify and use BLEU scores of hypotheses directly?
		float lossDiff = losses[indexFear] - losses[indexHope];
		delta = (lossDiff - diffOfModelScores) / squaredNorm;
		cout << "delta: " << delta << endl;
		cout << "loss diff - model diff: " << lossDiff << " - " << diffOfModelScores << endl;

		// clipping
		// fear translation: e_ij  --> alpha_ij  = alpha_ij  + delta
		// hope translation: e_ij' --> alpha_ij' = alpha_ij' - delta
		// clipping interval: [-alpha_ij, alpha_ij']
		// clip delta
		cout << "Interval [" << (-1 * alphas[indexFear]) << "," << alphas[indexHope] << "]" << endl;
		if (delta > alphas[indexHope]) {
			//cout << "clipping " << delta << " to " << alphas[indexHope] << endl;
			delta = alphas[indexHope];
		}
		else if (delta < (-1 * alphas[indexFear])) {
			//cout << "clipping " << delta << " to " << (-1 * alphas[indexFear]) << endl;
			delta = (-1 * alphas[indexFear]);
		}

		// update alphas
		alphas[indexHope] -= delta;
		alphas[indexFear] += delta;
		//cout << "alpha[" << indexHope << "] = " << alphas[indexHope] << endl;
		//cout << "alpha[" << indexFear << "] = " << alphas[indexFear] << endl;
	}

	return delta;
}

/*
 * Update the weight vector according to delta and the feature value difference
 * w' = w' + delta * (Dh_ij - Dh_ij') ---> w' = w' + delta * (h(e_ij') - h(e_ij)))
 */
void MiraOptimiser::update(ScoreComponentCollection& currWeights, ScoreComponentCollection& featureValueDiffs, const float delta) {
	featureValueDiffs.MultiplyEquals(delta);
	currWeights.PlusEquals(featureValueDiffs);
}

}

<commit_msg>fix hildreth<commit_after>#include "Optimiser.h"
#include "Hildreth.h"

using namespace Moses;
using namespace std;

namespace Mira {

void MiraOptimiser::updateWeights(ScoreComponentCollection& currWeights,
		const vector< vector<ScoreComponentCollection> >& featureValues,
		const vector< vector<float> >& losses,
		const ScoreComponentCollection& oracleFeatureValues) {

	if (m_hildreth) {
		size_t numberOfViolatedConstraints = 0;
		vector< ScoreComponentCollection> featureValueDiffs;
		vector< float> lossMarginDistances;
		for (size_t i = 0; i < featureValues.size(); ++i) {
			for (size_t j = 0; j < featureValues[i].size(); ++j) {
				// check if optimisation criterion is violated for one hypothesis and the oracle
				// h(e*) >= h(e_ij) + loss(e_ij)
				// h(e*) - h(e_ij) >= loss(e_ij)
				ScoreComponentCollection featureValueDiff = oracleFeatureValues;
				featureValueDiff.MinusEquals(featureValues[i][j]);
				float modelScoreDiff = featureValueDiff.InnerProduct(currWeights);
				if (modelScoreDiff < losses[i][j]) {
					cerr << "Constraint violated: " << modelScoreDiff << " (modelScoreDiff) < " << losses[i][j] << " (loss)" << endl;
					++numberOfViolatedConstraints;
				}
				else {
					cerr << "Constraint satisfied: " << modelScoreDiff << " (modelScoreDiff) >= " << losses[i][j] << " (loss)" << endl;
				}

				// Objective: 1/2 * ||w' - w||^2 + C * SUM_1_m[ max_1_n (l_ij - Delta_h_ij.w')]
				// To add a constraint for the optimiser for each sentence i and hypothesis j, we need:
				// 1. vector Delta_h_ij of the feature value differences (oracle - hypothesis)
				// 2. loss_ij - difference in model scores (Delta_h_ij.w') (oracle - hypothesis)
				featureValueDiffs.push_back(featureValueDiff);
				float lossMarginDistance = losses[i][j] - modelScoreDiff;
				lossMarginDistances.push_back(lossMarginDistance);
			}
		}

		if (numberOfViolatedConstraints > 0) {
			// run optimisation
			cerr << "Number of violated constraints: " << numberOfViolatedConstraints << endl;
			// TODO: slack? margin scale factor?
			// compute deltas for all given constraints
			vector< float> deltas = Hildreth::optimise(featureValueDiffs, lossMarginDistances);

			// Update the weight vector according to the deltas and the feature value differences
			// * w' = w' + delta * Dh_ij ---> w' = w' + delta * (h(e*) - h(e_ij))
			for (size_t k = 0; k < featureValueDiffs.size(); ++k) {
				// scale feature value differences with delta
				featureValueDiffs[k].MultiplyEquals(deltas[k]);

				// apply update to weight vector
				currWeights.PlusEquals(featureValueDiffs[k]);
			}
		}
		else {
			cout << "No constraint violated for this batch" << endl;
		}
	}
	else {
		// SMO:
		for (size_t i = 0; i < featureValues.size(); ++i) {
			// initialise alphas for each source (alpha for oracle translation = C, all other alphas = 0)
			vector< float> alphas(featureValues[i].size());
			for (size_t j = 0; j < featureValues[i].size(); ++j) {
				if (j == m_n) {										// TODO: use oracle index
					// oracle
					alphas[j] = m_c;
					//std::cout << "alpha " << j << ": " << alphas[j] << endl;
				}
				else {
					alphas[j] = 0;
					//std::cout << "alpha " << j << ": " << alphas[j] << endl;
				}
			}

			// consider all pairs of hypotheses
			size_t pairs = 0;
			for (size_t j = 0; j < featureValues[i].size(); ++j) {
				for (size_t k = 0; k < featureValues[i].size(); ++k) {
					if (j <= k) {
						++pairs;

						// Compute delta:
						cout << "\nComparing pair" << j << "," << k << endl;
						ScoreComponentCollection featureValueDiffs;
						float delta = computeDelta(currWeights, featureValues[i], j, k, losses[i], alphas, featureValueDiffs);

						// update weight vector:
						if (delta != 0) {
							update(currWeights, featureValueDiffs, delta);
						}
					}
				}
			}

			cout << "number of pairs: " << pairs << endl;
		}
	}
}

/*
 * Compute delta for weight update.
 * As part of this compute feature value differences
 * Dh_ij - Dh_ij' ---> h(e_ij') - h(e_ij)) --> h(hope) - h(fear)
 * which are used in the delta term and in the weight update term.
 */
float MiraOptimiser::computeDelta(ScoreComponentCollection& currWeights,
		const vector< ScoreComponentCollection>& featureValues,
		const size_t indexHope,
		const size_t indexFear,
		const vector< float>& losses,
		vector< float>& alphas,
		ScoreComponentCollection& featureValueDiffs) {

	const ScoreComponentCollection featureValuesHope = featureValues[indexHope];		// hypothesis j'
	const ScoreComponentCollection featureValuesFear = featureValues[indexFear];		// hypothesis j

	// compute delta
	float delta = 0.0;
	float diffOfModelScores = 0.0;		// (Dh_ij - Dh_ij') * w' --->  (h(e_ij') - h(e_ij))) * w' (inner product)
	float squaredNorm = 0.0;			// ||Dh_ij - Dh_ij'||^2  --->  sum over squares of elements of h(e_ij') - h(e_ij)

	featureValueDiffs = featureValuesHope;
	featureValueDiffs.MinusEquals(featureValuesFear);
	cout << "feature value diffs: " << featureValueDiffs << endl;
	squaredNorm = featureValueDiffs.InnerProduct(featureValueDiffs);
	diffOfModelScores = featureValueDiffs.InnerProduct(currWeights);

	if (squaredNorm == 0.0) {
		delta = 0.0;
	}
	else {
		// loss difference used to compute delta: (l_ij - l_ij')  --->  B(e_ij') - B(e_ij)
		// TODO: simplify and use BLEU scores of hypotheses directly?
		float lossDiff = losses[indexFear] - losses[indexHope];
		delta = (lossDiff - diffOfModelScores) / squaredNorm;
		cout << "delta: " << delta << endl;
		cout << "loss diff - model diff: " << lossDiff << " - " << diffOfModelScores << endl;

		// clipping
		// fear translation: e_ij  --> alpha_ij  = alpha_ij  + delta
		// hope translation: e_ij' --> alpha_ij' = alpha_ij' - delta
		// clipping interval: [-alpha_ij, alpha_ij']
		// clip delta
		cout << "Interval [" << (-1 * alphas[indexFear]) << "," << alphas[indexHope] << "]" << endl;
		if (delta > alphas[indexHope]) {
			//cout << "clipping " << delta << " to " << alphas[indexHope] << endl;
			delta = alphas[indexHope];
		}
		else if (delta < (-1 * alphas[indexFear])) {
			//cout << "clipping " << delta << " to " << (-1 * alphas[indexFear]) << endl;
			delta = (-1 * alphas[indexFear]);
		}

		// update alphas
		alphas[indexHope] -= delta;
		alphas[indexFear] += delta;
		//cout << "alpha[" << indexHope << "] = " << alphas[indexHope] << endl;
		//cout << "alpha[" << indexFear << "] = " << alphas[indexFear] << endl;
	}

	return delta;
}

/*
 * Update the weight vector according to delta and the feature value difference
 * w' = w' + delta * (Dh_ij - Dh_ij') ---> w' = w' + delta * (h(e_ij') - h(e_ij)))
 */
void MiraOptimiser::update(ScoreComponentCollection& currWeights, ScoreComponentCollection& featureValueDiffs, const float delta) {
	featureValueDiffs.MultiplyEquals(delta);
	currWeights.PlusEquals(featureValueDiffs);
}

}

<|endoftext|>


<commit_before>#include    <cstdlib>
#include    <cmath>
#include    <fstream>
#include    <sstream>
#include    <iostream>
#include        <cstring>
#include    <iomanip>
#include    <string>
#include    <vector>
#include    <algorithm>
#include    <exception>
#include    <sys/time.h>
#include        <map>
#include        <stdlib.h>     /* srand, rand */
#include        "misc.h"
#include        "collision.h"
#include        "feat.h"
// Features ------------------------------------------------------------------
Feat::Feat() {
    Count = 0;
    Categories = 0;
    MinDec = -90.0;
    MaxDec = 90.0;
    MinRa = 0.0;
    MaxRa = 360.0;
}

int Feat::id(str s) const {
    for (int i=0; i<Categories; i++) if (kind[i]==s) return i;
    std::cout << "ERROR in Feat id(), string not found in kind" << std::endl;
    return -1;
}

void Feat::init_ids() {
    for (int i=0; i<Categories; i++) ids[kind[i]] = i;
}

void Feat::init_ids_types() {
    for (int i=0; i<Categories; i++) ids_types[kind[i]] = i;
}

List Feat::init_ids_list(str l[], int size) const {
    List L;
    L.resize(size);
    for (int i=0; i<size; i++) L[i] = ids.at(l[i]);
    return L;
}

void Feat::init_types() {
    for (int i=0; i<type.size(); i++) if (!isfound(type[i],types)) types.push_back(type[i]);
}

void Feat::init_no_ss_sf() {
    //str noA[] = {"LRG","FakeLRG","ELG","QSOLy-a","QSOTracer","FakeQSO"};
    for(int i=0;i<kind.size()-2;++i)no_ss_sf.push_back(i);
    //no_ss_sf = init_ids_list(noA,6);
}

void Feat::init_ss_sf() {
    str A[] = {"SS","SF"};
    ss_sf = init_ids_list(A,2);
}

bool Feat::iftype(int kind, str type) const {
    return ids_types.at(type)==type[kind];
}

void Feat::readInputFile(const char file[]) {
    const int Mc = 512; // Max chars per line
    char delimiter = ' ';

	std::ifstream fIn;
	fIn.open(file); // open a file
	if (!fIn.good()) myexit(1); // Not found
	while (!fIn.eof()) {
		char buf[Mc];
		fIn.getline(buf,Mc);
		int n = 0; // a for-loop index
		Slist tok = s2vec(buf,delimiter);
		if (2<=tok.size()) {
			if (tok[0]=="galFile") galFile = tok[1];
			if (tok[0]=="tileFile") tileFile= tok[1];
			if (tok[0]=="fibFile") fibFile= tok[1];
            if (tok[0]=="surveyFile") surveyFile= tok[1];
			if (tok[0]=="outDir") outDir= tok[1];
			if (tok[0]=="PrintAscii") PrintAscii= s2b(tok[1]);
            if (tok[0]=="PrintFits") PrintFits= s2b(tok[1]);

            if (tok[0]=="MTLfile") MTLfile=tok[1];
            if (tok[0]=="Targfile") Targfile=tok[1];
            if (tok[0]=="SStarsfile")SStarsfile=tok[1];
            if (tok[0]=="SkyFfile") SkyFfile=tok[1];
            if (tok[0]=="Secretfile") Secretfile=tok[1];

            if (tok[0]=="diagnose") diagnose=s2b(tok[1]);

            if (tok[0]=="kind") {
                Categories = tok.size()-1;
                for (int i=0; i<Categories; i++) kind.push_back(tok[i+1]);
                init_ids();
                init_ss_sf();
                init_no_ss_sf();
            }
            if (tok[0]=="type") {
                Categories = tok.size()-1;
                for (int i=0; i<Categories; i++) type.push_back(tok[i+1]);
                init_types();
                init_ids_types();
            }
            if (tok[0]=="prio")  for (int i=0; i<Categories; i++){prio.push_back(s2i(tok[i+1]));}
            if (tok[0]=="priopost") for (int i=0; i<Categories; i++) priopost.push_back(s2i(tok[i+1]));
            if (tok[0]=="goal") for (int i=0; i<Categories; i++) goal.push_back(s2i(tok[i+1]));
            if (tok[0]=="goalpost") for (int i=0; i<Categories; i++) goalpost.push_back(s2i(tok[i+1]));
            if (tok[0]=="lastpass") for(int i=0; i<Categories;i++)lastpass.push_back(s2i(tok[i+1]));
            if (tok[0]=="SS") for(int i=0; i<Categories;i++)SS.push_back(s2i(tok[i+1]));
            if (tok[0]=="SF") for(int i=0; i<Categories;i++)SF.push_back(s2i(tok[i+1]));
            if (tok[0]=="pass_intervals"){
                int n_intervals=tok.size()-1;
                for (int i=0;i<n_intervals;++i) pass_intervals.push_back(s2i(tok[i+1]));
            }

      if (tok[0]=="InterPlate") InterPlate = s2i(tok[1]);
      if (tok[0]=="Randomize") Randomize = s2b(tok[1]);
      if (tok[0]=="Pacman") Pacman = s2b(tok[1]);
      if (tok[0]=="Npass") Npass = s2i(tok[1]);
      if (tok[0]=="MaxSS") MaxSS = s2i(tok[1]);
      if (tok[0]=="MaxSF") MaxSF = s2i(tok[1]);
      if (tok[0]=="PlateRadius") PlateRadius = s2d(tok[1]);
      if (tok[0]=="Analysis") Analysis = s2i(tok[1]);
      if (tok[0]=="InfDens") InfDens = s2b(tok[1]);

      if (tok[0]=="TotalArea") TotalArea = s2d(tok[1]);
      if (tok[0]=="invFibArea") invFibArea = s2d(tok[1]);
      if (tok[0]=="moduloGal") moduloGal = s2i(tok[1]);
      if (tok[0]=="moduloFiber") moduloFiber = s2i(tok[1]);

      if (tok[0]=="Collision") Collision = s2b(tok[1]);
      if (tok[0]=="Exact") Exact = s2b(tok[1]);
      if (tok[0]=="AvCollide") AvCollide = s2d(tok[1]);
      if (tok[0]=="Collide") Collide = s2d(tok[1]);
      if (tok[0]=="NoCollide") NoCollide = s2d(tok[1]);
      if (tok[0]=="PatrolRad") PatrolRad = s2d(tok[1]);
      if (tok[0]=="NeighborRad") NeighborRad = s2d(tok[1]);

      if (tok[0]=="PlotObsTime") PlotObsTime = s2b(tok[1]);
      if (tok[0]=="PlotHistLya") PlotHistLya = s2b(tok[1]);
      if (tok[0]=="PlotDistLya") PlotDistLya = s2b(tok[1]);
      if (tok[0]=="PlotFreeFibHist") PlotFreeFibHist = s2b(tok[1]);
      if (tok[0]=="PlotFreeFibTime") PlotFreeFibTime = s2b(tok[1]);
      if (tok[0]=="PlotSeenDens") PlotSeenDens = s2b(tok[1]);
      if (tok[0]=="Verif") Verif = s2b(tok[1]);
      if (tok[0]=="Ascii") Ascii = s2b(tok[1]);
      if (tok[0]=="PrintGalObs") PrintGalObs = s2i(tok[1]);
      if (tok[0]=="BrightTime") BrightTime = s2b(tok[1]);

      if (tok[0]=="MaxDec") MaxDec = s2d(tok[1]);
      if (tok[0]=="MinDec") MinDec = s2d(tok[1]);
      if (tok[0]=="MaxRa") MaxRa = s2d(tok[1]);
      if (tok[0]=="MinRa") MinRa = s2d(tok[1]);

    }
  }

  fIn.close();
}
<commit_msg>remove prio and priopost<commit_after>#include    <cstdlib>
#include    <cmath>
#include    <fstream>
#include    <sstream>
#include    <iostream>
#include        <cstring>
#include    <iomanip>
#include    <string>
#include    <vector>
#include    <algorithm>
#include    <exception>
#include    <sys/time.h>
#include        <map>
#include        <stdlib.h>     /* srand, rand */
#include        "misc.h"
#include        "collision.h"
#include        "feat.h"
// Features ------------------------------------------------------------------
Feat::Feat() {
    Count = 0;
    Categories = 0;
    MinDec = -90.0;
    MaxDec = 90.0;
    MinRa = 0.0;
    MaxRa = 360.0;
}

int Feat::id(str s) const {
    for (int i=0; i<Categories; i++) if (kind[i]==s) return i;
    std::cout << "ERROR in Feat id(), string not found in kind" << std::endl;
    return -1;
}

void Feat::init_ids() {
    for (int i=0; i<Categories; i++) ids[kind[i]] = i;
}

void Feat::init_ids_types() {
    for (int i=0; i<Categories; i++) ids_types[kind[i]] = i;
}

List Feat::init_ids_list(str l[], int size) const {
    List L;
    L.resize(size);
    for (int i=0; i<size; i++) L[i] = ids.at(l[i]);
    return L;
}

void Feat::init_types() {
    for (int i=0; i<type.size(); i++) if (!isfound(type[i],types)) types.push_back(type[i]);
}

void Feat::init_no_ss_sf() {
    //str noA[] = {"LRG","FakeLRG","ELG","QSOLy-a","QSOTracer","FakeQSO"};
    for(int i=0;i<kind.size()-2;++i)no_ss_sf.push_back(i);
    //no_ss_sf = init_ids_list(noA,6);
}

void Feat::init_ss_sf() {
    str A[] = {"SS","SF"};
    ss_sf = init_ids_list(A,2);
}

bool Feat::iftype(int kind, str type) const {
    return ids_types.at(type)==type[kind];
}

void Feat::readInputFile(const char file[]) {
    const int Mc = 512; // Max chars per line
    char delimiter = ' ';

	std::ifstream fIn;
	fIn.open(file); // open a file
	if (!fIn.good()) myexit(1); // Not found
	while (!fIn.eof()) {
		char buf[Mc];
		fIn.getline(buf,Mc);
		int n = 0; // a for-loop index
		Slist tok = s2vec(buf,delimiter);
		if (2<=tok.size()) {
			if (tok[0]=="galFile") galFile = tok[1];
			if (tok[0]=="tileFile") tileFile= tok[1];
			if (tok[0]=="fibFile") fibFile= tok[1];
            if (tok[0]=="surveyFile") surveyFile= tok[1];
			if (tok[0]=="outDir") outDir= tok[1];
			if (tok[0]=="PrintAscii") PrintAscii= s2b(tok[1]);
            if (tok[0]=="PrintFits") PrintFits= s2b(tok[1]);

            if (tok[0]=="MTLfile") MTLfile=tok[1];
            if (tok[0]=="Targfile") Targfile=tok[1];
            if (tok[0]=="SStarsfile")SStarsfile=tok[1];
            if (tok[0]=="SkyFfile") SkyFfile=tok[1];
            if (tok[0]=="Secretfile") Secretfile=tok[1];

            if (tok[0]=="diagnose") diagnose=s2b(tok[1]);

            if (tok[0]=="kind") {
                Categories = tok.size()-1;
                for (int i=0; i<Categories; i++) kind.push_back(tok[i+1]);
                init_ids();
                init_ss_sf();
                init_no_ss_sf();
            }
            if (tok[0]=="type") {
                Categories = tok.size()-1;
                for (int i=0; i<Categories; i++) type.push_back(tok[i+1]);
                init_types();
                init_ids_types();
            }
            //if (tok[0]=="prio")  for (int i=0; i<Categories; i++){prio.push_back(s2i(tok[i+1]));}
            //if (tok[0]=="priopost") for (int i=0; i<Categories; i++) priopost.push_back(s2i(tok[i+1]));
            if (tok[0]=="goal") for (int i=0; i<Categories; i++) goal.push_back(s2i(tok[i+1]));
            if (tok[0]=="goalpost") for (int i=0; i<Categories; i++) goalpost.push_back(s2i(tok[i+1]));
            if (tok[0]=="lastpass") for(int i=0; i<Categories;i++)lastpass.push_back(s2i(tok[i+1]));
            if (tok[0]=="SS") for(int i=0; i<Categories;i++)SS.push_back(s2i(tok[i+1]));
            if (tok[0]=="SF") for(int i=0; i<Categories;i++)SF.push_back(s2i(tok[i+1]));
            if (tok[0]=="pass_intervals"){
                int n_intervals=tok.size()-1;
                for (int i=0;i<n_intervals;++i) pass_intervals.push_back(s2i(tok[i+1]));
            }

      if (tok[0]=="InterPlate") InterPlate = s2i(tok[1]);
      if (tok[0]=="Randomize") Randomize = s2b(tok[1]);
      if (tok[0]=="Pacman") Pacman = s2b(tok[1]);
      if (tok[0]=="Npass") Npass = s2i(tok[1]);
      if (tok[0]=="MaxSS") MaxSS = s2i(tok[1]);
      if (tok[0]=="MaxSF") MaxSF = s2i(tok[1]);
      if (tok[0]=="PlateRadius") PlateRadius = s2d(tok[1]);
      if (tok[0]=="Analysis") Analysis = s2i(tok[1]);
      if (tok[0]=="InfDens") InfDens = s2b(tok[1]);

      if (tok[0]=="TotalArea") TotalArea = s2d(tok[1]);
      if (tok[0]=="invFibArea") invFibArea = s2d(tok[1]);
      if (tok[0]=="moduloGal") moduloGal = s2i(tok[1]);
      if (tok[0]=="moduloFiber") moduloFiber = s2i(tok[1]);

      if (tok[0]=="Collision") Collision = s2b(tok[1]);
      if (tok[0]=="Exact") Exact = s2b(tok[1]);
      if (tok[0]=="AvCollide") AvCollide = s2d(tok[1]);
      if (tok[0]=="Collide") Collide = s2d(tok[1]);
      if (tok[0]=="NoCollide") NoCollide = s2d(tok[1]);
      if (tok[0]=="PatrolRad") PatrolRad = s2d(tok[1]);
      if (tok[0]=="NeighborRad") NeighborRad = s2d(tok[1]);

      if (tok[0]=="PlotObsTime") PlotObsTime = s2b(tok[1]);
      if (tok[0]=="PlotHistLya") PlotHistLya = s2b(tok[1]);
      if (tok[0]=="PlotDistLya") PlotDistLya = s2b(tok[1]);
      if (tok[0]=="PlotFreeFibHist") PlotFreeFibHist = s2b(tok[1]);
      if (tok[0]=="PlotFreeFibTime") PlotFreeFibTime = s2b(tok[1]);
      if (tok[0]=="PlotSeenDens") PlotSeenDens = s2b(tok[1]);
      if (tok[0]=="Verif") Verif = s2b(tok[1]);
      if (tok[0]=="Ascii") Ascii = s2b(tok[1]);
      if (tok[0]=="PrintGalObs") PrintGalObs = s2i(tok[1]);
      if (tok[0]=="BrightTime") BrightTime = s2b(tok[1]);

      if (tok[0]=="MaxDec") MaxDec = s2d(tok[1]);
      if (tok[0]=="MinDec") MinDec = s2d(tok[1]);
      if (tok[0]=="MaxRa") MaxRa = s2d(tok[1]);
      if (tok[0]=="MinRa") MinRa = s2d(tok[1]);

    }
  }

  fIn.close();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: type_misc.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 23:37:51 $
 *
 *  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 _BRIDGES_CPP_UNO_TYPE_MISC_HXX_
#define _BRIDGES_CPP_UNO_TYPE_MISC_HXX_

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _TYPELIB_TYPEDESCRIPTION_H_
#include <typelib/typedescription.h>
#endif

/** Determines whether given type might relate or relates to an interface,
    i.e. values of this type are interface or may contain interface(s).

    @param pTypeDescr type description of type
    @return true if type might relate to an interface, false otherwise
*/
inline bool cppu_relatesToInterface( typelib_TypeDescription * pTypeDescr ) SAL_THROW( () )
{
    switch (pTypeDescr->eTypeClass)
    {
//      case typelib_TypeClass_TYPEDEF:
    case typelib_TypeClass_SEQUENCE:
    {
        switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass)
        {
        case typelib_TypeClass_INTERFACE:
        case typelib_TypeClass_UNION: // might relate to interface
        case typelib_TypeClass_ANY: // might relate to interface
            return true;
        case typelib_TypeClass_SEQUENCE:
        case typelib_TypeClass_STRUCT:
        case typelib_TypeClass_EXCEPTION:
        {
            typelib_TypeDescription * pTD = 0;
            TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
            bool bRel = cppu_relatesToInterface( pTD );
            TYPELIB_DANGER_RELEASE( pTD );
            return bRel;
        }
        default:
            return false;
        }
    }
    case typelib_TypeClass_STRUCT:
    case typelib_TypeClass_EXCEPTION:
    {
        // ...optimized... to avoid getDescription() calls!
        typelib_CompoundTypeDescription * pComp    = (typelib_CompoundTypeDescription *)pTypeDescr;
        typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
        for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
        {
            switch (pTypes[nPos]->eTypeClass)
            {
            case typelib_TypeClass_INTERFACE:
            case typelib_TypeClass_UNION: // might relate to interface
            case typelib_TypeClass_ANY: // might relate to interface
                return true;
//              case typelib_TypeClass_TYPEDEF:
            case typelib_TypeClass_SEQUENCE:
            case typelib_TypeClass_STRUCT:
            case typelib_TypeClass_EXCEPTION:
            {
                typelib_TypeDescription * pTD = 0;
                TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
                bool bRel = cppu_relatesToInterface( pTD );
                TYPELIB_DANGER_RELEASE( pTD );
                if (bRel)
                    return true;
            }
            default:
                break;
            }
        }
        if (pComp->pBaseTypeDescription)
            return cppu_relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription );
        return false;
    }
    case typelib_TypeClass_UNION: // might relate to interface
    case typelib_TypeClass_ANY: // might relate to interface
    case typelib_TypeClass_INTERFACE:
        return true;
    default:
        return false;
    }
}

/** Determines whether given type is a cpp simple type, e.g. int, enum.

    @param eTypeClass type class of type
    @return true if type is a cpp simple type, false otherwise
*/
inline bool cppu_isSimpleType( typelib_TypeClass eTypeClass ) SAL_THROW( () )
{
    return (eTypeClass <= typelib_TypeClass_ENUM &&
            eTypeClass != typelib_TypeClass_STRING &&
            eTypeClass != typelib_TypeClass_ANY &&
            eTypeClass != typelib_TypeClass_TYPE);
}
/** Determines whether given type is a cpp simple type, e.g. int, enum.

    @param pTypeDescr type description of type
    @return true if type is a cpp simple type, false otherwise
*/
inline bool cppu_isSimpleType( typelib_TypeDescription * pTypeDescr ) SAL_THROW( () )
{
    return cppu_isSimpleType( pTypeDescr->eTypeClass );
}

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.122); FILE MERGED 2008/04/01 15:02:32 thb 1.5.122.2: #i85898# Stripping all external header guards 2008/03/28 16:29:51 rt 1.5.122.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: type_misc.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _BRIDGES_CPP_UNO_TYPE_MISC_HXX_
#define _BRIDGES_CPP_UNO_TYPE_MISC_HXX_

#include <sal/types.h>
#include <typelib/typedescription.h>

/** Determines whether given type might relate or relates to an interface,
    i.e. values of this type are interface or may contain interface(s).

    @param pTypeDescr type description of type
    @return true if type might relate to an interface, false otherwise
*/
inline bool cppu_relatesToInterface( typelib_TypeDescription * pTypeDescr ) SAL_THROW( () )
{
    switch (pTypeDescr->eTypeClass)
    {
//      case typelib_TypeClass_TYPEDEF:
    case typelib_TypeClass_SEQUENCE:
    {
        switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass)
        {
        case typelib_TypeClass_INTERFACE:
        case typelib_TypeClass_UNION: // might relate to interface
        case typelib_TypeClass_ANY: // might relate to interface
            return true;
        case typelib_TypeClass_SEQUENCE:
        case typelib_TypeClass_STRUCT:
        case typelib_TypeClass_EXCEPTION:
        {
            typelib_TypeDescription * pTD = 0;
            TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
            bool bRel = cppu_relatesToInterface( pTD );
            TYPELIB_DANGER_RELEASE( pTD );
            return bRel;
        }
        default:
            return false;
        }
    }
    case typelib_TypeClass_STRUCT:
    case typelib_TypeClass_EXCEPTION:
    {
        // ...optimized... to avoid getDescription() calls!
        typelib_CompoundTypeDescription * pComp    = (typelib_CompoundTypeDescription *)pTypeDescr;
        typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
        for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
        {
            switch (pTypes[nPos]->eTypeClass)
            {
            case typelib_TypeClass_INTERFACE:
            case typelib_TypeClass_UNION: // might relate to interface
            case typelib_TypeClass_ANY: // might relate to interface
                return true;
//              case typelib_TypeClass_TYPEDEF:
            case typelib_TypeClass_SEQUENCE:
            case typelib_TypeClass_STRUCT:
            case typelib_TypeClass_EXCEPTION:
            {
                typelib_TypeDescription * pTD = 0;
                TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
                bool bRel = cppu_relatesToInterface( pTD );
                TYPELIB_DANGER_RELEASE( pTD );
                if (bRel)
                    return true;
            }
            default:
                break;
            }
        }
        if (pComp->pBaseTypeDescription)
            return cppu_relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription );
        return false;
    }
    case typelib_TypeClass_UNION: // might relate to interface
    case typelib_TypeClass_ANY: // might relate to interface
    case typelib_TypeClass_INTERFACE:
        return true;
    default:
        return false;
    }
}

/** Determines whether given type is a cpp simple type, e.g. int, enum.

    @param eTypeClass type class of type
    @return true if type is a cpp simple type, false otherwise
*/
inline bool cppu_isSimpleType( typelib_TypeClass eTypeClass ) SAL_THROW( () )
{
    return (eTypeClass <= typelib_TypeClass_ENUM &&
            eTypeClass != typelib_TypeClass_STRING &&
            eTypeClass != typelib_TypeClass_ANY &&
            eTypeClass != typelib_TypeClass_TYPE);
}
/** Determines whether given type is a cpp simple type, e.g. int, enum.

    @param pTypeDescr type description of type
    @return true if type is a cpp simple type, false otherwise
*/
inline bool cppu_isSimpleType( typelib_TypeDescription * pTypeDescr ) SAL_THROW( () )
{
    return cppu_isSimpleType( pTypeDescr->eTypeClass );
}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: urp_marshal.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: ihi $ $Date: 2008-02-04 13:44:16 $
 *
 *  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 _URP_MARSHAL_HXX_
#define _URP_MARSHAL_HXX_
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _RTL_BYTESEQ_HXX_
#include <rtl/byteseq.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_TYPE_HXX_
#include <com/sun/star/uno/Type.hxx>
#endif

#ifndef _URP_BRIDGEIMPL_HXX_
#include "urp_bridgeimpl.hxx"
#endif

#ifndef _URP_MARSHAL_DECL_HXX_
#include "urp_marshal_decl.hxx"
#endif

#include <string.h>

struct remote_Interface;

namespace bridges_urp
{
    // methods for accessing marshaling buffer
    inline void Marshal::finish( sal_Int32 nMessageCount )
    {
        sal_Int32 nSize = getSize() - 2*sizeof( sal_Int32 );

        // save the state
        sal_Int8 *pos = m_pos;
        m_pos = m_base;
        packInt32( &nSize );
        packInt32( &nMessageCount );

        // reset the state
        m_pos = pos;
    }

    inline void Marshal::restart()
    {
        m_pos = m_base + 2*sizeof( sal_Int32 );
    }

    inline sal_Int8 *Marshal::getBuffer()
    {
        return m_base;
    }

    inline sal_Bool Marshal::empty() const
    {
        return ( m_pos - m_base ) == 2*sizeof( sal_Int32 );
    }

    inline sal_Int32 Marshal::getSize()
    {
        return ((sal_Int32) (m_pos - m_base));
    }

    inline void Marshal::ensureAdditionalMem( sal_Int32 nMemToAdd )
    {
        sal_Int32 nDiff = m_pos - m_base;
        if( nDiff + nMemToAdd > m_nBufferSize )
        {
            m_nBufferSize = m_nBufferSize * 2 > nDiff + nMemToAdd ?
                m_nBufferSize* 2 :
                nDiff + nMemToAdd;

            m_base = ( sal_Int8 * ) rtl_reallocateMemory( m_base , m_nBufferSize );
            m_pos = m_base + nDiff;
        }
    }

    // marshaling methods
    inline void Marshal::packInt8( void *pSource )
    {
        ensureAdditionalMem( 1 );
        *m_pos = *((sal_Int8*) pSource );
        m_pos++;
    }

    inline void Marshal::packInt16( void *pSource )
    {
        ensureAdditionalMem( 2 );
        if( isSystemLittleEndian() )
        {
            m_pos[0] = ((unsigned char *)pSource)[1];
            m_pos[1] = ((unsigned char *)pSource)[0];
        }
        else
        {
            m_pos[1] = ((unsigned char *)pSource)[1];
            m_pos[0] = ((unsigned char *)pSource)[0];
        }
        m_pos +=2;
    }

    inline void Marshal::packByteSequence( sal_Int8 *pData , sal_Int32 nLength )
    {
        packCompressedSize( nLength );

        ensureAdditionalMem( nLength );
        memcpy( m_pos , pData , nLength );
        m_pos += nLength;
    }

    inline void Marshal::packString( void *pSource )
    {
        rtl_uString *p = *( rtl_uString ** ) pSource;

        // to be optimized !
        // static buffer in marshal
        ::rtl::OString o = ::rtl::OUStringToOString( p , RTL_TEXTENCODING_UTF8 );
        sal_Int32 nLength = o.pData->length;
        packCompressedSize( nLength );

        ensureAdditionalMem( nLength );

        memcpy( m_pos , o.pData->buffer , nLength  );
        m_pos += nLength;
    }

    inline sal_Bool Marshal::packAny( void *pSource )
    {
        sal_Bool bSuccess = sal_True;
        uno_Any *pAny = (uno_Any * ) pSource;

        // pack the type
        packType( &( pAny->pType ) );
        // pack the value
        typelib_TypeDescription *pType = 0;
        TYPELIB_DANGER_GET( &pType, pAny->pType );
        if( pType )
        {
            pack( pAny->pData , pType );
            TYPELIB_DANGER_RELEASE( pType );
        }
        else
        {
            rtl::OUStringBuffer buf( 128 );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("couldn't get typedescription for type " ) );
            buf.append( pAny->pType->pTypeName );
            m_pBridgeImpl->addError( buf.makeStringAndClear() );
            bSuccess = sal_False;
        }
        return bSuccess;
    }

    inline void Marshal::packInt32( void *pSource )
    {
        ensureAdditionalMem( 4 );
        if( isSystemLittleEndian() )
        {
            m_pos[0] = ((unsigned char *)pSource)[3];
            m_pos[1] = ((unsigned char *)pSource)[2];
            m_pos[2] = ((unsigned char *)pSource)[1];
            m_pos[3] = ((unsigned char *)pSource)[0];
        }
        else {
            m_pos[3] = ((unsigned char *)pSource)[3];
            m_pos[2] = ((unsigned char *)pSource)[2];
            m_pos[1] = ((unsigned char *)pSource)[1];
            m_pos[0] = ((unsigned char *)pSource)[0];
        }
        m_pos +=4;
    }

    inline void Marshal::packCompressedSize( sal_Int32 nSize )
    {
        ensureAdditionalMem( 5 );

        if( nSize < 0xff )
        {
            *((sal_uInt8*)m_pos) = (sal_uInt8) nSize;
            m_pos ++;
        }
        else
        {
            *((sal_uInt8*)m_pos) = 0xff;
            m_pos ++;
            packInt32( &nSize );
        }
    }

    inline sal_Bool Marshal::pack( void *pSource , typelib_TypeDescription *pType )
    {
        sal_Bool bSuccess = sal_True;
        switch( pType->eTypeClass )
        {
        case typelib_TypeClass_BYTE:
        {
            packInt8( pSource );
            break;
        }
        case typelib_TypeClass_BOOLEAN:
        {
            ensureAdditionalMem( 1 );
            *m_pos = ( *((sal_Bool*) pSource ) ) ? 1 : 0;
            m_pos++;
            break;
        }

        case typelib_TypeClass_CHAR:
        case typelib_TypeClass_SHORT:
        case typelib_TypeClass_UNSIGNED_SHORT:
        {
            packInt16( pSource );
            break;
        }
        case typelib_TypeClass_ENUM:
        case typelib_TypeClass_LONG:
        case typelib_TypeClass_UNSIGNED_LONG:
        case typelib_TypeClass_FLOAT:
        {
            packInt32( pSource );
            break;
        }
        case typelib_TypeClass_DOUBLE:
        case typelib_TypeClass_HYPER:
        case typelib_TypeClass_UNSIGNED_HYPER:
        {
            ensureAdditionalMem( 8 );
            if( isSystemLittleEndian() )
            {
                m_pos[0] = ((unsigned char *)pSource)[7];
                m_pos[1] = ((unsigned char *)pSource)[6];
                m_pos[2] = ((unsigned char *)pSource)[5];
                m_pos[3] = ((unsigned char *)pSource)[4];
                m_pos[4] = ((unsigned char *)pSource)[3];
                m_pos[5] = ((unsigned char *)pSource)[2];
                m_pos[6] = ((unsigned char *)pSource)[1];
                m_pos[7] = ((unsigned char *)pSource)[0];
            }
            else
            {
                m_pos[7] = ((unsigned char *)pSource)[7];
                m_pos[6] = ((unsigned char *)pSource)[6];
                m_pos[5] = ((unsigned char *)pSource)[5];
                m_pos[4] = ((unsigned char *)pSource)[4];
                m_pos[3] = ((unsigned char *)pSource)[3];
                m_pos[2] = ((unsigned char *)pSource)[2];
                m_pos[1] = ((unsigned char *)pSource)[1];
                m_pos[0] = ((unsigned char *)pSource)[0];
            }
            m_pos += 8;
            break;
        }

        case typelib_TypeClass_STRING:
        {
            packString( pSource );
            break;
        }
        case typelib_TypeClass_TYPE:
        {
            packType( pSource );
            break;
        }
        case typelib_TypeClass_ANY:
        {
            bSuccess = packAny( pSource );
            break;
        }
        case typelib_TypeClass_TYPEDEF:
        {
            bSuccess = sal_False;
            m_pBridgeImpl->addError( "can't handle typedef typedescriptions" );
            break;
        }
        case typelib_TypeClass_INTERFACE:
        {
            remote_Interface *pRemoteI = *( remote_Interface ** )pSource;

            ::rtl::OUString sOid;
            sal_uInt16 nIndex = 0xffff;
            if( pRemoteI )
            {
                m_callback( pRemoteI , &(sOid.pData) );

                nIndex = m_pBridgeImpl->m_oidCacheOut.seek( sOid );
                if( 0xffff == nIndex )
                {
                    nIndex = m_pBridgeImpl->m_oidCacheOut.put( sOid );
                }
                else
                {
                    // cached !
                    sOid = ::rtl::OUString();
                }
            }
            packString( &sOid );
            packInt16( &nIndex );
            break;
        }
        case typelib_TypeClass_VOID:
        {
            // do nothing
            break;
        }
        case typelib_TypeClass_EXCEPTION:
        case typelib_TypeClass_STRUCT:
        case typelib_TypeClass_SEQUENCE:
        {
            bSuccess = packRecursive( pSource, pType );
            break;
        }
        default:
        {
            bSuccess = sal_False;
            rtl::OUStringBuffer buf( 128 );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "can't handle values with typeclass " ) );
            buf.append( (sal_Int32 ) pType->eTypeClass , 10 );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
            buf.append( pType->pTypeName );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
            m_pBridgeImpl->addError( buf.makeStringAndClear() );
            break;
        }
        }
        return bSuccess;
    }
}

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.8.14); FILE MERGED 2008/04/01 15:02:36 thb 1.8.14.3: #i85898# Stripping all external header guards 2008/04/01 10:49:07 thb 1.8.14.2: #i85898# Stripping all external header guards 2008/03/28 16:30:59 rt 1.8.14.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: urp_marshal.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _URP_MARSHAL_HXX_
#define _URP_MARSHAL_HXX_
#include <rtl/ustrbuf.hxx>
#include <rtl/byteseq.hxx>
#include <com/sun/star/uno/Type.hxx>
#include "urp_bridgeimpl.hxx"
#include "urp_marshal_decl.hxx"

#include <string.h>

struct remote_Interface;

namespace bridges_urp
{
    // methods for accessing marshaling buffer
    inline void Marshal::finish( sal_Int32 nMessageCount )
    {
        sal_Int32 nSize = getSize() - 2*sizeof( sal_Int32 );

        // save the state
        sal_Int8 *pos = m_pos;
        m_pos = m_base;
        packInt32( &nSize );
        packInt32( &nMessageCount );

        // reset the state
        m_pos = pos;
    }

    inline void Marshal::restart()
    {
        m_pos = m_base + 2*sizeof( sal_Int32 );
    }

    inline sal_Int8 *Marshal::getBuffer()
    {
        return m_base;
    }

    inline sal_Bool Marshal::empty() const
    {
        return ( m_pos - m_base ) == 2*sizeof( sal_Int32 );
    }

    inline sal_Int32 Marshal::getSize()
    {
        return ((sal_Int32) (m_pos - m_base));
    }

    inline void Marshal::ensureAdditionalMem( sal_Int32 nMemToAdd )
    {
        sal_Int32 nDiff = m_pos - m_base;
        if( nDiff + nMemToAdd > m_nBufferSize )
        {
            m_nBufferSize = m_nBufferSize * 2 > nDiff + nMemToAdd ?
                m_nBufferSize* 2 :
                nDiff + nMemToAdd;

            m_base = ( sal_Int8 * ) rtl_reallocateMemory( m_base , m_nBufferSize );
            m_pos = m_base + nDiff;
        }
    }

    // marshaling methods
    inline void Marshal::packInt8( void *pSource )
    {
        ensureAdditionalMem( 1 );
        *m_pos = *((sal_Int8*) pSource );
        m_pos++;
    }

    inline void Marshal::packInt16( void *pSource )
    {
        ensureAdditionalMem( 2 );
        if( isSystemLittleEndian() )
        {
            m_pos[0] = ((unsigned char *)pSource)[1];
            m_pos[1] = ((unsigned char *)pSource)[0];
        }
        else
        {
            m_pos[1] = ((unsigned char *)pSource)[1];
            m_pos[0] = ((unsigned char *)pSource)[0];
        }
        m_pos +=2;
    }

    inline void Marshal::packByteSequence( sal_Int8 *pData , sal_Int32 nLength )
    {
        packCompressedSize( nLength );

        ensureAdditionalMem( nLength );
        memcpy( m_pos , pData , nLength );
        m_pos += nLength;
    }

    inline void Marshal::packString( void *pSource )
    {
        rtl_uString *p = *( rtl_uString ** ) pSource;

        // to be optimized !
        // static buffer in marshal
        ::rtl::OString o = ::rtl::OUStringToOString( p , RTL_TEXTENCODING_UTF8 );
        sal_Int32 nLength = o.pData->length;
        packCompressedSize( nLength );

        ensureAdditionalMem( nLength );

        memcpy( m_pos , o.pData->buffer , nLength  );
        m_pos += nLength;
    }

    inline sal_Bool Marshal::packAny( void *pSource )
    {
        sal_Bool bSuccess = sal_True;
        uno_Any *pAny = (uno_Any * ) pSource;

        // pack the type
        packType( &( pAny->pType ) );
        // pack the value
        typelib_TypeDescription *pType = 0;
        TYPELIB_DANGER_GET( &pType, pAny->pType );
        if( pType )
        {
            pack( pAny->pData , pType );
            TYPELIB_DANGER_RELEASE( pType );
        }
        else
        {
            rtl::OUStringBuffer buf( 128 );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("couldn't get typedescription for type " ) );
            buf.append( pAny->pType->pTypeName );
            m_pBridgeImpl->addError( buf.makeStringAndClear() );
            bSuccess = sal_False;
        }
        return bSuccess;
    }

    inline void Marshal::packInt32( void *pSource )
    {
        ensureAdditionalMem( 4 );
        if( isSystemLittleEndian() )
        {
            m_pos[0] = ((unsigned char *)pSource)[3];
            m_pos[1] = ((unsigned char *)pSource)[2];
            m_pos[2] = ((unsigned char *)pSource)[1];
            m_pos[3] = ((unsigned char *)pSource)[0];
        }
        else {
            m_pos[3] = ((unsigned char *)pSource)[3];
            m_pos[2] = ((unsigned char *)pSource)[2];
            m_pos[1] = ((unsigned char *)pSource)[1];
            m_pos[0] = ((unsigned char *)pSource)[0];
        }
        m_pos +=4;
    }

    inline void Marshal::packCompressedSize( sal_Int32 nSize )
    {
        ensureAdditionalMem( 5 );

        if( nSize < 0xff )
        {
            *((sal_uInt8*)m_pos) = (sal_uInt8) nSize;
            m_pos ++;
        }
        else
        {
            *((sal_uInt8*)m_pos) = 0xff;
            m_pos ++;
            packInt32( &nSize );
        }
    }

    inline sal_Bool Marshal::pack( void *pSource , typelib_TypeDescription *pType )
    {
        sal_Bool bSuccess = sal_True;
        switch( pType->eTypeClass )
        {
        case typelib_TypeClass_BYTE:
        {
            packInt8( pSource );
            break;
        }
        case typelib_TypeClass_BOOLEAN:
        {
            ensureAdditionalMem( 1 );
            *m_pos = ( *((sal_Bool*) pSource ) ) ? 1 : 0;
            m_pos++;
            break;
        }

        case typelib_TypeClass_CHAR:
        case typelib_TypeClass_SHORT:
        case typelib_TypeClass_UNSIGNED_SHORT:
        {
            packInt16( pSource );
            break;
        }
        case typelib_TypeClass_ENUM:
        case typelib_TypeClass_LONG:
        case typelib_TypeClass_UNSIGNED_LONG:
        case typelib_TypeClass_FLOAT:
        {
            packInt32( pSource );
            break;
        }
        case typelib_TypeClass_DOUBLE:
        case typelib_TypeClass_HYPER:
        case typelib_TypeClass_UNSIGNED_HYPER:
        {
            ensureAdditionalMem( 8 );
            if( isSystemLittleEndian() )
            {
                m_pos[0] = ((unsigned char *)pSource)[7];
                m_pos[1] = ((unsigned char *)pSource)[6];
                m_pos[2] = ((unsigned char *)pSource)[5];
                m_pos[3] = ((unsigned char *)pSource)[4];
                m_pos[4] = ((unsigned char *)pSource)[3];
                m_pos[5] = ((unsigned char *)pSource)[2];
                m_pos[6] = ((unsigned char *)pSource)[1];
                m_pos[7] = ((unsigned char *)pSource)[0];
            }
            else
            {
                m_pos[7] = ((unsigned char *)pSource)[7];
                m_pos[6] = ((unsigned char *)pSource)[6];
                m_pos[5] = ((unsigned char *)pSource)[5];
                m_pos[4] = ((unsigned char *)pSource)[4];
                m_pos[3] = ((unsigned char *)pSource)[3];
                m_pos[2] = ((unsigned char *)pSource)[2];
                m_pos[1] = ((unsigned char *)pSource)[1];
                m_pos[0] = ((unsigned char *)pSource)[0];
            }
            m_pos += 8;
            break;
        }

        case typelib_TypeClass_STRING:
        {
            packString( pSource );
            break;
        }
        case typelib_TypeClass_TYPE:
        {
            packType( pSource );
            break;
        }
        case typelib_TypeClass_ANY:
        {
            bSuccess = packAny( pSource );
            break;
        }
        case typelib_TypeClass_TYPEDEF:
        {
            bSuccess = sal_False;
            m_pBridgeImpl->addError( "can't handle typedef typedescriptions" );
            break;
        }
        case typelib_TypeClass_INTERFACE:
        {
            remote_Interface *pRemoteI = *( remote_Interface ** )pSource;

            ::rtl::OUString sOid;
            sal_uInt16 nIndex = 0xffff;
            if( pRemoteI )
            {
                m_callback( pRemoteI , &(sOid.pData) );

                nIndex = m_pBridgeImpl->m_oidCacheOut.seek( sOid );
                if( 0xffff == nIndex )
                {
                    nIndex = m_pBridgeImpl->m_oidCacheOut.put( sOid );
                }
                else
                {
                    // cached !
                    sOid = ::rtl::OUString();
                }
            }
            packString( &sOid );
            packInt16( &nIndex );
            break;
        }
        case typelib_TypeClass_VOID:
        {
            // do nothing
            break;
        }
        case typelib_TypeClass_EXCEPTION:
        case typelib_TypeClass_STRUCT:
        case typelib_TypeClass_SEQUENCE:
        {
            bSuccess = packRecursive( pSource, pType );
            break;
        }
        default:
        {
            bSuccess = sal_False;
            rtl::OUStringBuffer buf( 128 );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "can't handle values with typeclass " ) );
            buf.append( (sal_Int32 ) pType->eTypeClass , 10 );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
            buf.append( pType->pTypeName );
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
            m_pBridgeImpl->addError( buf.makeStringAndClear() );
            break;
        }
        }
        return bSuccess;
    }
}

#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifdef WIN32

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef int mode_t;

#else

#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#endif

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

namespace fs = boost::filesystem;

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
//		if (m == (mode_in | mode_out)) return O_RDWR | O_BINARY;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		assert(false);
		return 0;
	}
}

namespace libtorrent
{

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			close();
			m_fd = ::open(
				path.native_file_string().c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

			std::stringstream str;
			str << "fd: " << m_fd << "\n";

			::close(m_fd);
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_in);
			assert(m_fd != -1);

			size_type ret = ::read(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_out);
			assert(m_fd != -1);

			size_type ret = ::write(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void seek(size_type offset, int m)
		{
			assert(m_open_mode);
			assert(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}

		}

		size_type tell()
		{
			assert(m_open_mode);
			assert(m_fd != -1);

#ifdef WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(boost::filesystem::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(boost::filesystem::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	void file::seek(size_type pos, file::seek_mode m)
	{
		m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifdef WIN32

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#else

#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#endif

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

namespace fs = boost::filesystem;

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
//		if (m == (mode_in | mode_out)) return O_RDWR | O_BINARY;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		assert(false);
		return 0;
	}
}

namespace libtorrent
{

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			close();
			m_fd = ::open(
				path.native_file_string().c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

			std::stringstream str;
			str << "fd: " << m_fd << "\n";

			::close(m_fd);
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_in);
			assert(m_fd != -1);

			size_type ret = ::read(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_out);
			assert(m_fd != -1);

			size_type ret = ::write(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void seek(size_type offset, int m)
		{
			assert(m_open_mode);
			assert(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}

		}

		size_type tell()
		{
			assert(m_open_mode);
			assert(m_fd != -1);

#ifdef WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(boost::filesystem::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(boost::filesystem::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	void file::seek(size_type pos, file::seek_mode m)
	{
		m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<|endoftext|>


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

#include "browser/atom_javascript_dialog_manager.h"

#include "base/utf_string_conversions.h"

namespace atom {

void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
    content::WebContents* web_contents,
    const string16& message_text,
    bool is_reload,
    const DialogClosedCallback& callback) {
  bool prevent_reload = !message_text.empty() ||
                        message_text == ASCIIToUTF16("false");
  callback.Run(!prevent_reload, message_text);
}

}  // namespace atom
<commit_msg>Revert ":lipstick: for the beforeunload handler."<commit_after>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "browser/atom_javascript_dialog_manager.h"

#include "base/utf_string_conversions.h"

namespace atom {

void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
    content::WebContents* web_contents,
    const string16& message_text,
    bool is_reload,
    const DialogClosedCallback& callback) {

  bool prevent_reload = message_text.empty() ||
                        message_text == ASCIIToUTF16("false");
  callback.Run(!prevent_reload, message_text);
}

}  // namespace atom
<|endoftext|>