<commit_before>#pragma once

#include <stdint.h>

/* XXX: Comment out this line for a non-test network */
//#define BTS_TEST_NETWORK

#define BTS_TEST_NETWORK_VERSION                            83 // autogenerated

#define BTS_BLOCKCHAIN_DATABASE_VERSION                     uint64_t( 199 )

#define BTS_ADDRESS_PREFIX                                  "BTS"
#define BTS_BLOCKCHAIN_SYMBOL                               "BTS"
#define BTS_BLOCKCHAIN_NAME                                 "BitShares"
#define BTS_BLOCKCHAIN_DESCRIPTION                          "Decentralized Exchange"
#define BTS_BLOCKCHAIN_PRECISION                            100000

#define BTS_BLOCKCHAIN_MAX_UIA_MARKET_FEE                   10000
#define BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC                   int64_t(10)
#define BTS_BLOCKCHAIN_BLOCKS_PER_HOUR                      ((60*60)/BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC)
#define BTS_BLOCKCHAIN_BLOCKS_PER_DAY                       (BTS_BLOCKCHAIN_BLOCKS_PER_HOUR*int64_t(24))
#define BTS_BLOCKCHAIN_BLOCKS_PER_YEAR                      (BTS_BLOCKCHAIN_BLOCKS_PER_DAY*int64_t(365))

#define BTS_BLOCKCHAIN_NUM_DELEGATES                        uint32_t(101)
#define BTS_MAX_DELEGATE_PAY_PER_BLOCK                      int64_t( 50 * BTS_BLOCKCHAIN_PRECISION ) // 50 XTS
#define BTS_BLOCKCHAIN_MAX_UNDO_HISTORY                     BTS_BLOCKCHAIN_BLOCKS_PER_HOUR

#define BTS_BLOCKCHAIN_MAX_SLATE_SIZE                       (BTS_BLOCKCHAIN_NUM_DELEGATES + (BTS_BLOCKCHAIN_NUM_DELEGATES/10))
#define BTS_BLOCKCHAIN_MAX_TRANSACTION_EXPIRATION_SEC       (60*60*24*2)
#define BTS_BLOCKCHAIN_MAX_MEMO_SIZE                        19 // bytes
#define BTS_BLOCKCHAIN_EXTENDED_MEMO_SIZE                   32 // bytes
#define BTS_BLOCKCHAIN_MAX_EXTENDED_MEMO_SIZE               (BTS_BLOCKCHAIN_MAX_MEMO_SIZE + BTS_BLOCKCHAIN_EXTENDED_MEMO_SIZE)

/**
 *  The maximum amount that can be issued for user assets.
 *
 *  10^18 / 2^63 < 1  however, to support representing all share values as a double in
 *  languages like java script, we must stay within the epsilon so
 *
 *  10^15 / 2^53 < 1 allows all values to be represented as a double or an int64
 */
#define BTS_BLOCKCHAIN_MAX_SHARES                           (1000*1000*int64_t(1000)*1000*int64_t(1000))

#define BTS_BLOCKCHAIN_MIN_NAME_SIZE                        1
#define BTS_BLOCKCHAIN_MAX_NAME_SIZE                        63
#define BTS_BLOCKCHAIN_MAX_NAME_DATA_SIZE                   (1024*64)

#define BTS_BLOCKCHAIN_MAX_SUB_SYMBOL_SIZE                  8 // characters
#define BTS_BLOCKCHAIN_MIN_SYMBOL_SIZE                      3 // characters
#define BTS_BLOCKCHAIN_MAX_SYMBOL_SIZE                      12 // characters

#define BTS_BLOCKCHAIN_MIN_BURN_FEE                         BTS_BLOCKCHAIN_PRECISION * 1 // 1 XTS

#ifdef BTS_TEST_NETWORK
#define BTS_BLOCKCHAIN_VOTE_UPDATE_PERIOD_SEC               10
#else
#define BTS_BLOCKCHAIN_VOTE_UPDATE_PERIOD_SEC               (60*60) // 1 hour
#endif

#define BTS_BLOCKCHAIN_MIN_FEEDS                            ((BTS_BLOCKCHAIN_NUM_DELEGATES/2) + 1)
#define BTS_BLOCKCHAIN_MINIMUM_SHORT_ORDER_SIZE             (BTS_BLOCKCHAIN_PRECISION*100)
#define BTS_BLOCKCHAIN_MIN_YIELD_PERIOD_SEC                 (60*60*24) // 24 hours
#define BTS_BLOCKCHAIN_MAX_YIELD_PERIOD_SEC                 (BTS_BLOCKCHAIN_BLOCKS_PER_YEAR * BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC) // 1 year

#ifdef BTS_TEST_NETWORK
#define BTS_BLOCKCHAIN_MAX_SHORT_PERIOD_SEC                 (2*60*60) // 2 hours
#else
#define BTS_BLOCKCHAIN_MAX_SHORT_PERIOD_SEC                 (30*24*60*60) // 1 month
#endif
#define BTS_BLOCKCHAIN_MAX_SHORT_APR_PCT                    (uint64_t(1000))

#define BTS_BLOCKCHAIN_MCALL_D2C_NUMERATOR                  1
#define BTS_BLOCKCHAIN_MCALL_D2C_DENOMINATOR                2

// TODO: This stuff only matters for propagation throttling; should go somewhere else
#define BTS_BLOCKCHAIN_DEFAULT_RELAY_FEE                    10000 // XTS
#define BTS_BLOCKCHAIN_MAX_TRX_PER_SECOND                   1  // (10)
#define BTS_BLOCKCHAIN_MAX_PENDING_QUEUE_SIZE               10 // (BTS_BLOCKCHAIN_MAX_TRX_PER_SECOND * BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC)
<commit_msg>changing max APR to 50%<commit_after>#pragma once

#include <stdint.h>

/* XXX: Comment out this line for a non-test network */
//#define BTS_TEST_NETWORK

#define BTS_TEST_NETWORK_VERSION                            83 // autogenerated

#define BTS_BLOCKCHAIN_DATABASE_VERSION                     uint64_t( 199 )

#define BTS_ADDRESS_PREFIX                                  "BTS"
#define BTS_BLOCKCHAIN_SYMBOL                               "BTS"
#define BTS_BLOCKCHAIN_NAME                                 "BitShares"
#define BTS_BLOCKCHAIN_DESCRIPTION                          "Decentralized Exchange"
#define BTS_BLOCKCHAIN_PRECISION                            100000

#define BTS_BLOCKCHAIN_MAX_UIA_MARKET_FEE                   10000
#define BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC                   int64_t(10)
#define BTS_BLOCKCHAIN_BLOCKS_PER_HOUR                      ((60*60)/BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC)
#define BTS_BLOCKCHAIN_BLOCKS_PER_DAY                       (BTS_BLOCKCHAIN_BLOCKS_PER_HOUR*int64_t(24))
#define BTS_BLOCKCHAIN_BLOCKS_PER_YEAR                      (BTS_BLOCKCHAIN_BLOCKS_PER_DAY*int64_t(365))

#define BTS_BLOCKCHAIN_NUM_DELEGATES                        uint32_t(101)
#define BTS_MAX_DELEGATE_PAY_PER_BLOCK                      int64_t( 50 * BTS_BLOCKCHAIN_PRECISION ) // 50 XTS
#define BTS_BLOCKCHAIN_MAX_UNDO_HISTORY                     BTS_BLOCKCHAIN_BLOCKS_PER_HOUR

#define BTS_BLOCKCHAIN_MAX_SLATE_SIZE                       (BTS_BLOCKCHAIN_NUM_DELEGATES + (BTS_BLOCKCHAIN_NUM_DELEGATES/10))
#define BTS_BLOCKCHAIN_MAX_TRANSACTION_EXPIRATION_SEC       (60*60*24*2)
#define BTS_BLOCKCHAIN_MAX_MEMO_SIZE                        19 // bytes
#define BTS_BLOCKCHAIN_EXTENDED_MEMO_SIZE                   32 // bytes
#define BTS_BLOCKCHAIN_MAX_EXTENDED_MEMO_SIZE               (BTS_BLOCKCHAIN_MAX_MEMO_SIZE + BTS_BLOCKCHAIN_EXTENDED_MEMO_SIZE)

/**
 *  The maximum amount that can be issued for user assets.
 *
 *  10^18 / 2^63 < 1  however, to support representing all share values as a double in
 *  languages like java script, we must stay within the epsilon so
 *
 *  10^15 / 2^53 < 1 allows all values to be represented as a double or an int64
 */
#define BTS_BLOCKCHAIN_MAX_SHARES                           (1000*1000*int64_t(1000)*1000*int64_t(1000))

#define BTS_BLOCKCHAIN_MIN_NAME_SIZE                        1
#define BTS_BLOCKCHAIN_MAX_NAME_SIZE                        63
#define BTS_BLOCKCHAIN_MAX_NAME_DATA_SIZE                   (1024*64)

#define BTS_BLOCKCHAIN_MAX_SUB_SYMBOL_SIZE                  8 // characters
#define BTS_BLOCKCHAIN_MIN_SYMBOL_SIZE                      3 // characters
#define BTS_BLOCKCHAIN_MAX_SYMBOL_SIZE                      12 // characters

#define BTS_BLOCKCHAIN_MIN_BURN_FEE                         BTS_BLOCKCHAIN_PRECISION * 1 // 1 XTS

#ifdef BTS_TEST_NETWORK
#define BTS_BLOCKCHAIN_VOTE_UPDATE_PERIOD_SEC               10
#else
#define BTS_BLOCKCHAIN_VOTE_UPDATE_PERIOD_SEC               (60*60) // 1 hour
#endif

#define BTS_BLOCKCHAIN_MIN_FEEDS                            ((BTS_BLOCKCHAIN_NUM_DELEGATES/2) + 1)
#define BTS_BLOCKCHAIN_MINIMUM_SHORT_ORDER_SIZE             (BTS_BLOCKCHAIN_PRECISION*100)
#define BTS_BLOCKCHAIN_MIN_YIELD_PERIOD_SEC                 (60*60*24) // 24 hours
#define BTS_BLOCKCHAIN_MAX_YIELD_PERIOD_SEC                 (BTS_BLOCKCHAIN_BLOCKS_PER_YEAR * BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC) // 1 year

#ifdef BTS_TEST_NETWORK
#define BTS_BLOCKCHAIN_MAX_SHORT_PERIOD_SEC                 (2*60*60) // 2 hours
#else
#define BTS_BLOCKCHAIN_MAX_SHORT_PERIOD_SEC                 (30*24*60*60) // 1 month
#endif
#define BTS_BLOCKCHAIN_MAX_SHORT_APR_PCT                    (uint64_t(50))

#define BTS_BLOCKCHAIN_MCALL_D2C_NUMERATOR                  1
#define BTS_BLOCKCHAIN_MCALL_D2C_DENOMINATOR                2

// TODO: This stuff only matters for propagation throttling; should go somewhere else
#define BTS_BLOCKCHAIN_DEFAULT_RELAY_FEE                    10000 // XTS
#define BTS_BLOCKCHAIN_MAX_TRX_PER_SECOND                   1  // (10)
#define BTS_BLOCKCHAIN_MAX_PENDING_QUEUE_SIZE               10 // (BTS_BLOCKCHAIN_MAX_TRX_PER_SECOND * BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC)
<|endoftext|>


<commit_before>#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <stdexcept>

#include "shunting-yard.h"

double toDouble(TokenBase* base) {
  if(base->type == NUM) {
    return static_cast<Token<double>*>(base)->val;
  } else {
    throw std::domain_error(
      "Cannot convert non numeric types to double!");
  }
}

void assert(double actual, double expected, const char* expr = 0) {
  double diff = actual - expected;
  if (diff < 0) diff *= -1;
  if (diff < 1e-15) {
    if(expr) {
      std::cout << "  '" << expr << "' indeed evaluated to " <<
        expected << "." << std::endl;
    } else {
      std::cout << "  actual value '" << actual <<
        "' indeed matches the expected value '" << expected << "'" << std::endl;
    }
  } else {
    if(expr) {
      std::cout << "  FAILURE '" << expr << "' evaluated to " <<
        actual << " and NOT " << expected << "!" << std::endl;
    } else {
      std::cout << "  FAILURE, actual value '" << actual <<
        "' does not match the expected value '" << expected <<
        "'" << std::endl;
    }
  }
}
void assert(const char* expr, double expected,
    TokenMap_t* vars = 0) {
  double actual = toDouble(calculator::calculate(expr, vars));
  assert(actual, expected, expr);
}

#define assert_throws(a) {try {\
  a; \
  std::cout << "  FAILURE, it did not THROW as expected" << std::endl; \
} catch(...) { \
  std::cout << "  THROWS as expected" << std::endl; \
}}

#define assert_not_throw(a) {try {\
  a; \
  std::cout << "  Do not THROW as expected" << std::endl; \
} catch(...) { \
  std::cout << "  FAILURE, it did THROW which was unexpected" << std::endl; \
}}

int main(int argc, char** argv) {
  TokenMap_t vars;
  vars["pi"] = 3.14;
  vars["b1"] = 0;

  std::cout << "\nTests with static calculate::calculate()\n" << std::endl;

  assert("-pi + 1", -2.14, &vars);
  assert("-pi + 1 * b1", -3.14, &vars);

  assert("(20+10)*3/2-3", 42.0);
  assert("1 << 4", 16.0);
  assert("1+(-2*3)", -5);

  std::cout << "\nTests with calculate::compile() & calculate::eval()\n" << std::endl;

  calculator c1;
  c1.compile("-pi+1", &vars);
  assert(toDouble(c1.eval()), -2.14);

  calculator c2("pi+4", &vars);
  assert(toDouble(c2.eval()), 7.14);
  assert(toDouble(c2.eval()), 7.14);

  calculator c3("pi+b1+b2", &vars);

  vars["b2"] = 1;
  assert(toDouble(c3.eval(&vars)), 4.14);

  vars["b2"] = .86;
  assert(toDouble(c3.eval(&vars)), 4);

  std::cout << "\nTesting boolean expressions\n" << std::endl;

  assert("3 < 3", false);
  assert("3 <= 3", true);
  assert("3 > 3", false);
  assert("3 >= 3", true);
  assert("3 == 3", true);
  assert("3 != 3", false);

  assert("(3 && true) == true", true);
  assert("(3 && 0) == true", false);
  assert("(3 || 0) == true", true);
  assert("(false || 0) == true", false);

  std::cout << "\nTesting string expressions\n" << std::endl;

  vars["str1"] = new Token<std::string>("foo", STR);
  vars["str2"] = new Token<std::string>("bar", STR);
  vars["str3"] = new Token<std::string>("foobar", STR);
  vars["str4"] = new Token<std::string>("foo10", STR);
  vars["str5"] = new Token<std::string>("10bar", STR);

  assert("str1 + str2 == str3", true, &vars);
  assert("str1 + str2 != str3", false, &vars);
  assert("str1 + 10 == str4", true, &vars);
  assert("10 + str2 == str5", true, &vars);

  assert("'foo' + \"bar\" == str3", true, &vars);
  assert("'foo' + \"bar\" != 'foobar\"'", true, &vars);
  assert("'foo' + \"bar\\\"\" == 'foobar\"'", true, &vars);

  std::cout << "\nTesting exception management\n" << std::endl;

  assert_throws(c3.eval());

  assert_throws({
    vars.erase("b2");
    c3.eval(&vars);
  });

  assert_not_throw({
    vars["b2"] = 0;
    vars.erase("b1");
    c3.eval(&vars);
  });

  std::cout << "\nEnd testing" << std::endl;

  return 0;
}
<commit_msg>Update assert function to work with any type of Token<commit_after>#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <stdexcept>

#include "shunting-yard.h"

void assert(packToken actual, packToken expected, const char* expr = 0) {
  bool match = false;
  if(actual->type == expected->type && actual->type == NUM) {
    double diff = actual.asDouble() - expected.asDouble();
    if (diff < 0) diff *= -1;
    if (diff < 1e-15) match = true;
  } else if(actual == expected) {
    match = true;
  }

  if(match) {
    if(expr) {
      std::cout << "  '" << expr << "' indeed evaluated to " <<
        expected << "." << std::endl;
    } else {
      std::cout << "  actual value '" << actual <<
        "' indeed matches the expected value '" << expected << "'" << std::endl;
    }
  } else {
    if(expr) {
      std::cout << "  FAILURE '" << expr << "' evaluated to " <<
        actual << " and NOT " << expected << "!" << std::endl;
    } else {
      std::cout << "  FAILURE, actual value '" << actual <<
        "' does not match the expected value '" << expected <<
        "'" << std::endl;
    }
  }
}
void assert(const char* expr, packToken expected,
    TokenMap_t* vars = 0) {
  packToken actual = calculator::calculate(expr, vars);
  assert(actual, expected, expr);
}

#define assert_throws(a) {try {\
  a; \
  std::cout << "  FAILURE, it did not THROW as expected" << std::endl; \
} catch(...) { \
  std::cout << "  THROWS as expected" << std::endl; \
}}

#define assert_not_throw(a) {try {\
  a; \
  std::cout << "  Do not THROW as expected" << std::endl; \
} catch(...) { \
  std::cout << "  FAILURE, it did THROW which was unexpected" << std::endl; \
}}

int main(int argc, char** argv) {
  TokenMap_t vars;
  vars["pi"] = 3.14;
  vars["b1"] = 0;

  std::cout << "\nTests with static calculate::calculate()\n" << std::endl;

  assert("-pi + 1", -2.14, &vars);
  assert("-pi + 1 * b1", -3.14, &vars);

  assert("(20+10)*3/2-3", 42.0);
  assert("1 << 4", 16.0);
  assert("1+(-2*3)", -5);

  std::cout << "\nTests with calculate::compile() & calculate::eval()\n" << std::endl;

  calculator c1;
  c1.compile("-pi+1", &vars);
  assert(c1.eval(), -2.14);

  calculator c2("pi+4", &vars);
  assert(c2.eval(), 7.14);
  assert(c2.eval(), 7.14);

  calculator c3("pi+b1+b2", &vars);

  vars["b2"] = 1;
  assert(c3.eval(&vars), 4.14);

  vars["b2"] = .86;
  assert(c3.eval(&vars), 4);

  std::cout << "\nTesting boolean expressions\n" << std::endl;

  assert("3 < 3", false);
  assert("3 <= 3", true);
  assert("3 > 3", false);
  assert("3 >= 3", true);
  assert("3 == 3", true);
  assert("3 != 3", false);

  assert("(3 && true) == true", true);
  assert("(3 && 0) == true", false);
  assert("(3 || 0) == true", true);
  assert("(false || 0) == true", false);

  std::cout << "\nTesting string expressions\n" << std::endl;

  vars["str1"] = new Token<std::string>("foo", STR);
  vars["str2"] = new Token<std::string>("bar", STR);
  vars["str3"] = new Token<std::string>("foobar", STR);
  vars["str4"] = new Token<std::string>("foo10", STR);
  vars["str5"] = new Token<std::string>("10bar", STR);

  assert("str1 + str2 == str3", true, &vars);
  assert("str1 + str2 != str3", false, &vars);
  assert("str1 + 10 == str4", true, &vars);
  assert("10 + str2 == str5", true, &vars);

  assert("'foo' + \"bar\" == str3", true, &vars);
  assert("'foo' + \"bar\" != 'foobar\"'", true, &vars);
  assert("'foo' + \"bar\\\"\" == 'foobar\"'", true, &vars);

  std::cout << "\nTesting exception management\n" << std::endl;

  assert_throws(c3.eval());

  assert_throws({
    vars.erase("b2");
    c3.eval(&vars);
  });

  assert_not_throw({
    vars["b2"] = 0;
    vars.erase("b1");
    c3.eval(&vars);
  });

  std::cout << "\nEnd testing" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: calendarImpl.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: khong $ $Date: 2002-07-12 17:25:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "calendarImpl.hxx"
#include "localedata.hxx"
#include <comphelper/processfactory.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::i18n;
using namespace ::rtl;

#define ERROR RuntimeException()

CalendarImpl::CalendarImpl(const Reference< XMultiServiceFactory > &rxMSF) : xMSF(rxMSF)
{
}

CalendarImpl::~CalendarImpl()
{
    // Clear lookuptable
    for (lookupTableItem *listItem = (lookupTableItem*)lookupTable.First();
                listItem; listItem = (lookupTableItem*)lookupTable.Next())
        delete listItem;
    lookupTable.Clear();
}

void SAL_CALL
CalendarImpl::loadDefaultCalendar( const Locale& rLocale ) throw(RuntimeException)
{
    loadCalendar(OUString(), rLocale);
}

void SAL_CALL
CalendarImpl::loadCachedCalendar(OUString& uniqueID) throw (RuntimeException)
{
    for (lookupTableItem *listItem = (lookupTableItem*)lookupTable.First();
            listItem; listItem = (lookupTableItem*)lookupTable.Next()) {
        if (uniqueID == listItem->uniqueID) {
        xCalendar = listItem->xCalendar;
        return;
        }
    }

    Reference < XInterface > xI = xMSF->createInstance(
        OUString::createFromAscii("com.sun.star.i18n.Calendar_") + uniqueID);
    if ( xI.is() )
        xI->queryInterface(::getCppuType((const Reference< XExtendedCalendar>*)0)) >>= xCalendar;
    else
        throw ERROR;

    lookupTable.Insert( new lookupTableItem(uniqueID, xCalendar) );
}

void SAL_CALL
CalendarImpl::loadCalendar( const OUString& uniqueID, const Locale& rLocale ) throw(RuntimeException)
{
    aLocale = rLocale;
    Sequence< Calendar> xC = LocaleData().getAllCalendars(rLocale);
    for (sal_Int32 i = 0; i < xC.getLength(); i++) {
        if ( (uniqueID.getLength() != 0) ? (uniqueID == xC[i].Name) : (xC[i].Default == sal_True) ) {
        aCalendar = xC[i];
        loadCachedCalendar(aCalendar.Name);
        if (xCalendar.is())
            xCalendar->loadCalendar(uniqueID, aLocale);
        // setup first day of week
        for (aStartOfWeek = aCalendar.Days.getLength()-1; aStartOfWeek>=0; aStartOfWeek-- )
            if (aCalendar.StartOfWeek == aCalendar.Days[aStartOfWeek].ID)
            return;
        }
    }
    throw ERROR;
}

Calendar SAL_CALL
CalendarImpl::getLoadedCalendar() throw(RuntimeException)
{
    return aCalendar;
}

Sequence< OUString > SAL_CALL
CalendarImpl::getAllCalendars( const Locale& rLocale ) throw(RuntimeException)
{
    Sequence< Calendar> xC = LocaleData().getAllCalendars(rLocale);
    sal_Int32 nLen = xC.getLength();
    Sequence< OUString > xSeq( nLen );
    for (sal_Int32 i = 0; i < nLen; i++)
        xSeq[i] = xC[i].Name;
    return xSeq;
}

void SAL_CALL
CalendarImpl::setDateTime( double timeInDays ) throw(RuntimeException)
{
    if (xCalendar.is())
        xCalendar->setDateTime( timeInDays );
    else
        throw ERROR ;
}

double SAL_CALL
CalendarImpl::getDateTime() throw(RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->getDateTime();
    else
        throw ERROR ;
}

OUString SAL_CALL
CalendarImpl::getUniqueID() throw(RuntimeException)
{
    return aCalendar.Name;
}

void SAL_CALL
CalendarImpl::setValue( sal_Int16 fieldIndex, sal_Int16 value ) throw(RuntimeException)
{
    if (xCalendar.is())
        xCalendar->setValue( fieldIndex, value );
    else
        throw ERROR ;
}

sal_Int16 SAL_CALL
CalendarImpl::getValue( sal_Int16 fieldIndex ) throw(RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->getValue( fieldIndex );
    else
        throw ERROR ;
}

void SAL_CALL
CalendarImpl::addValue( sal_Int16 fieldIndex, sal_Int32 amount ) throw(RuntimeException)
{
    if (xCalendar.is())
        xCalendar->addValue( fieldIndex, amount);
    else
        throw ERROR ;
}

sal_Int16 SAL_CALL
CalendarImpl::getFirstDayOfWeek() throw(RuntimeException)
{
    return aStartOfWeek;
}

void SAL_CALL
CalendarImpl::setFirstDayOfWeek( sal_Int16 day )
throw(RuntimeException)
{
    aStartOfWeek = day;
}

void SAL_CALL
CalendarImpl::setMinimumNumberOfDaysForFirstWeek( sal_Int16 days ) throw(RuntimeException)
{
    aCalendar.MinimumNumberOfDaysForFirstWeek = days;
}

sal_Int16 SAL_CALL
CalendarImpl::getMinimumNumberOfDaysForFirstWeek() throw(RuntimeException)
{
    return aCalendar.MinimumNumberOfDaysForFirstWeek;
}

OUString SAL_CALL
CalendarImpl::getDisplayName( sal_Int16 displayIndex, sal_Int16 idx, sal_Int16 nameType ) throw(RuntimeException)
{
    OUString aStr;

    switch( displayIndex ) {
        case CalendarDisplayIndex::AM_PM:/* ==0 */
        if (idx == 0) aStr = LocaleData().getLocaleItem(aLocale).timeAM;
        else if (idx == 1) aStr = LocaleData().getLocaleItem(aLocale).timePM;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::DAY:
        if( idx >= aCalendar.Days.getLength() ) throw ERROR;
        if (nameType == 0) aStr = aCalendar.Days[idx].AbbrevName;
        else if (nameType == 1) aStr = aCalendar.Days[idx].FullName;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::MONTH:
        if( idx >= aCalendar.Months.getLength() ) throw ERROR;
        if (nameType == 0) aStr = aCalendar.Months[idx].AbbrevName;
        else if (nameType == 1) aStr = aCalendar.Months[idx].FullName;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::ERA:
        if( idx >= aCalendar.Eras.getLength() ) throw ERROR;
        if (nameType == 0) aStr = aCalendar.Eras[idx].AbbrevName;
        else if (nameType == 1) aStr = aCalendar.Eras[idx].FullName;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::YEAR:
        break;
        default:
        throw ERROR;
    }
    return aStr;
}

sal_Int16 SAL_CALL
CalendarImpl::getNumberOfMonthsInYear() throw(RuntimeException)
{
    return (sal_Int16) aCalendar.Months.getLength();
}

sal_Int16 SAL_CALL
CalendarImpl::getNumberOfDaysInWeek() throw(RuntimeException)
{
    return (sal_Int16) aCalendar.Days.getLength();
}

Sequence< CalendarItem > SAL_CALL
CalendarImpl::getMonths() throw(RuntimeException)
{
    return aCalendar.Months;
}

Sequence< CalendarItem > SAL_CALL
CalendarImpl::getDays() throw(RuntimeException)
{
    return aCalendar.Days;
}

sal_Bool SAL_CALL
CalendarImpl::isValid() throw(RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->isValid();
    else
        throw ERROR ;
}

OUString SAL_CALL
CalendarImpl::getDisplayString( sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode )
    throw (RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->getDisplayString(nCalendarDisplayCode, nNativeNumberMode);
    else
        throw ERROR ;
}

OUString SAL_CALL
CalendarImpl::getImplementationName(void) throw( RuntimeException )
{
    return OUString::createFromAscii("com.sun.star.i18n.CalendarImpl");
}

const sal_Char cCalendar[] = "com.sun.star.i18n.LocaleCalendar";

sal_Bool SAL_CALL
CalendarImpl::supportsService(const OUString& rServiceName) throw( RuntimeException )
{
    return !rServiceName.compareToAscii(cCalendar);
}

Sequence< OUString > SAL_CALL
CalendarImpl::getSupportedServiceNames(void) throw( RuntimeException )
{
    Sequence< OUString > aRet(1);
    aRet[0] = OUString::createFromAscii(cCalendar);
    return aRet;
}

<commit_msg>#98695# add drafts namespace (why was only MSC bothered? How did other compilers know?)<commit_after>/*************************************************************************
 *
 *  $RCSfile: calendarImpl.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: er $ $Date: 2002-07-16 09:52:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "calendarImpl.hxx"
#include "localedata.hxx"
#include <comphelper/processfactory.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::i18n;
using namespace ::drafts::com::sun::star::i18n;
using namespace ::rtl;

#define ERROR RuntimeException()

CalendarImpl::CalendarImpl(const Reference< XMultiServiceFactory > &rxMSF) : xMSF(rxMSF)
{
}

CalendarImpl::~CalendarImpl()
{
    // Clear lookuptable
    for (lookupTableItem *listItem = (lookupTableItem*)lookupTable.First();
                listItem; listItem = (lookupTableItem*)lookupTable.Next())
        delete listItem;
    lookupTable.Clear();
}

void SAL_CALL
CalendarImpl::loadDefaultCalendar( const Locale& rLocale ) throw(RuntimeException)
{
    loadCalendar(OUString(), rLocale);
}

void SAL_CALL
CalendarImpl::loadCachedCalendar(OUString& uniqueID) throw (RuntimeException)
{
    for (lookupTableItem *listItem = (lookupTableItem*)lookupTable.First();
            listItem; listItem = (lookupTableItem*)lookupTable.Next()) {
        if (uniqueID == listItem->uniqueID) {
        xCalendar = listItem->xCalendar;
        return;
        }
    }

    Reference < XInterface > xI = xMSF->createInstance(
        OUString::createFromAscii("com.sun.star.i18n.Calendar_") + uniqueID);
    if ( xI.is() )
        xI->queryInterface(::getCppuType((const Reference< XExtendedCalendar>*)0)) >>= xCalendar;
    else
        throw ERROR;

    lookupTable.Insert( new lookupTableItem(uniqueID, xCalendar) );
}

void SAL_CALL
CalendarImpl::loadCalendar( const OUString& uniqueID, const Locale& rLocale ) throw(RuntimeException)
{
    aLocale = rLocale;
    Sequence< Calendar> xC = LocaleData().getAllCalendars(rLocale);
    for (sal_Int32 i = 0; i < xC.getLength(); i++) {
        if ( (uniqueID.getLength() != 0) ? (uniqueID == xC[i].Name) : (xC[i].Default == sal_True) ) {
        aCalendar = xC[i];
        loadCachedCalendar(aCalendar.Name);
        if (xCalendar.is())
            xCalendar->loadCalendar(uniqueID, aLocale);
        // setup first day of week
        for (aStartOfWeek = aCalendar.Days.getLength()-1; aStartOfWeek>=0; aStartOfWeek-- )
            if (aCalendar.StartOfWeek == aCalendar.Days[aStartOfWeek].ID)
            return;
        }
    }
    throw ERROR;
}

Calendar SAL_CALL
CalendarImpl::getLoadedCalendar() throw(RuntimeException)
{
    return aCalendar;
}

Sequence< OUString > SAL_CALL
CalendarImpl::getAllCalendars( const Locale& rLocale ) throw(RuntimeException)
{
    Sequence< Calendar> xC = LocaleData().getAllCalendars(rLocale);
    sal_Int32 nLen = xC.getLength();
    Sequence< OUString > xSeq( nLen );
    for (sal_Int32 i = 0; i < nLen; i++)
        xSeq[i] = xC[i].Name;
    return xSeq;
}

void SAL_CALL
CalendarImpl::setDateTime( double timeInDays ) throw(RuntimeException)
{
    if (xCalendar.is())
        xCalendar->setDateTime( timeInDays );
    else
        throw ERROR ;
}

double SAL_CALL
CalendarImpl::getDateTime() throw(RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->getDateTime();
    else
        throw ERROR ;
}

OUString SAL_CALL
CalendarImpl::getUniqueID() throw(RuntimeException)
{
    return aCalendar.Name;
}

void SAL_CALL
CalendarImpl::setValue( sal_Int16 fieldIndex, sal_Int16 value ) throw(RuntimeException)
{
    if (xCalendar.is())
        xCalendar->setValue( fieldIndex, value );
    else
        throw ERROR ;
}

sal_Int16 SAL_CALL
CalendarImpl::getValue( sal_Int16 fieldIndex ) throw(RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->getValue( fieldIndex );
    else
        throw ERROR ;
}

void SAL_CALL
CalendarImpl::addValue( sal_Int16 fieldIndex, sal_Int32 amount ) throw(RuntimeException)
{
    if (xCalendar.is())
        xCalendar->addValue( fieldIndex, amount);
    else
        throw ERROR ;
}

sal_Int16 SAL_CALL
CalendarImpl::getFirstDayOfWeek() throw(RuntimeException)
{
    return aStartOfWeek;
}

void SAL_CALL
CalendarImpl::setFirstDayOfWeek( sal_Int16 day )
throw(RuntimeException)
{
    aStartOfWeek = day;
}

void SAL_CALL
CalendarImpl::setMinimumNumberOfDaysForFirstWeek( sal_Int16 days ) throw(RuntimeException)
{
    aCalendar.MinimumNumberOfDaysForFirstWeek = days;
}

sal_Int16 SAL_CALL
CalendarImpl::getMinimumNumberOfDaysForFirstWeek() throw(RuntimeException)
{
    return aCalendar.MinimumNumberOfDaysForFirstWeek;
}

OUString SAL_CALL
CalendarImpl::getDisplayName( sal_Int16 displayIndex, sal_Int16 idx, sal_Int16 nameType ) throw(RuntimeException)
{
    OUString aStr;

    switch( displayIndex ) {
        case CalendarDisplayIndex::AM_PM:/* ==0 */
        if (idx == 0) aStr = LocaleData().getLocaleItem(aLocale).timeAM;
        else if (idx == 1) aStr = LocaleData().getLocaleItem(aLocale).timePM;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::DAY:
        if( idx >= aCalendar.Days.getLength() ) throw ERROR;
        if (nameType == 0) aStr = aCalendar.Days[idx].AbbrevName;
        else if (nameType == 1) aStr = aCalendar.Days[idx].FullName;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::MONTH:
        if( idx >= aCalendar.Months.getLength() ) throw ERROR;
        if (nameType == 0) aStr = aCalendar.Months[idx].AbbrevName;
        else if (nameType == 1) aStr = aCalendar.Months[idx].FullName;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::ERA:
        if( idx >= aCalendar.Eras.getLength() ) throw ERROR;
        if (nameType == 0) aStr = aCalendar.Eras[idx].AbbrevName;
        else if (nameType == 1) aStr = aCalendar.Eras[idx].FullName;
        else throw ERROR;
        break;
        case CalendarDisplayIndex::YEAR:
        break;
        default:
        throw ERROR;
    }
    return aStr;
}

sal_Int16 SAL_CALL
CalendarImpl::getNumberOfMonthsInYear() throw(RuntimeException)
{
    return (sal_Int16) aCalendar.Months.getLength();
}

sal_Int16 SAL_CALL
CalendarImpl::getNumberOfDaysInWeek() throw(RuntimeException)
{
    return (sal_Int16) aCalendar.Days.getLength();
}

Sequence< CalendarItem > SAL_CALL
CalendarImpl::getMonths() throw(RuntimeException)
{
    return aCalendar.Months;
}

Sequence< CalendarItem > SAL_CALL
CalendarImpl::getDays() throw(RuntimeException)
{
    return aCalendar.Days;
}

sal_Bool SAL_CALL
CalendarImpl::isValid() throw(RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->isValid();
    else
        throw ERROR ;
}

OUString SAL_CALL
CalendarImpl::getDisplayString( sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode )
    throw (RuntimeException)
{
    if (xCalendar.is())
        return xCalendar->getDisplayString(nCalendarDisplayCode, nNativeNumberMode);
    else
        throw ERROR ;
}

OUString SAL_CALL
CalendarImpl::getImplementationName(void) throw( RuntimeException )
{
    return OUString::createFromAscii("com.sun.star.i18n.CalendarImpl");
}

const sal_Char cCalendar[] = "com.sun.star.i18n.LocaleCalendar";

sal_Bool SAL_CALL
CalendarImpl::supportsService(const OUString& rServiceName) throw( RuntimeException )
{
    return !rServiceName.compareToAscii(cCalendar);
}

Sequence< OUString > SAL_CALL
CalendarImpl::getSupportedServiceNames(void) throw( RuntimeException )
{
    Sequence< OUString > aRet(1);
    aRet[0] = OUString::createFromAscii(cCalendar);
    return aRet;
}

<|endoftext|>


<commit_before>// This is improperly intended code
// Beautify.uc will fix this

const int MyEquate = 0x100;
const int Other = 0x200;

long ProgStatus;

#if defined Other
// Something
#elif !defined abcd
// Something else
#else
// Etc
#endif

struct point {
   long x;
   long y;
}

long MyFunction(long a, float& b)
{
   long x;
   long y;
   long *Test = new long [a+25+1];
   long yVar;

   // Dim q As Long
   // I don't want the commented line above to be translated

   MySub(a);
   x = MySub(b)+1;

   if (b > 5) {
      for (x=1; x<=10; x += 1) {
         for (yVar=10; yVar>=1; yVar += -1) {
            if (x > y) {
               return a+y;
            }
            if (y < MyEquate) {
               return Test[x-y]*10;
            }
         }
      }
   }

   delete[] Test;
}

void MySub(long x)
{
   long y;
   long *Test;
   float *Number = new float [10+1];
   long *Other = new long [x+1];
   long z;

   ProgStatus = 10;
   y = x + 1;
   z = y+x;
   Other[x] = x+1;

   while (x < 10) {
      y = MyFunction(x, 10.5);
      Test = &x;
      Number[z] = *Test + Other[5+x];
      x = x+1;
   }

   delete[] Other;
   delete[] Other;
}
<commit_msg>Update AfterBeautify.cpp<commit_after>// This is improperly intended code
// Beautify.uc will fix this

const int MyEquate = 0x100;
const int Other = 0x200;

long ProgStatus;

#if defined Other
// Something
#elif !defined abcd
// Something else
#else
// Etc
#endif

struct point {
   long x;
   long y;
}

long MyFunction(long a, float& b)
{
   long x;
   long y;
   long *Test = new long [a+25+1];
   long yVar;

   // Dim q As Long
   // I don't want the commented line above to be translated

   MySub(a);
   x = MySub(b)+1;
   printf("Hello world");

   if (b > 5) {
      for (x=1; x<=10; x += 1) {
         for (yVar=10; yVar>=1; yVar += -1) {
            if (x > y) {
               return a+y;
            }
            if (y < MyEquate) {
               return Test[x-y]*10;
            }
         }
      }
   }

   delete[] Test;
}

void MySub(long x)
{
   long y;
   long *Test;
   float *Number = new float [10+1];
   long *Other = new long [x+1];
   long z;

   ProgStatus = 10;
   y = x + 1;
   z = y+x;
   Other[x] = x+1;

   while (x < 10) {
      y = MyFunction(x, 10.5);
      Test = &x;
      Number[z] = *Test + Other[5+x];
      x = x+1;
   }

   if (x > 5) {
      y = 10;
      z = 5+x;
   } else {
      y=y+1;
      z=x-1;
   }

   delete[] Other;
   delete[] Other;
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "OgreMaterialDefines.h"
#include "CoreStringUtils.h"
#include "LoggingFunctions.h"

#include <Engine/Core/StringUtils.h>

namespace Tundra
{

namespace Ogre
{

// MaterialBlock

MaterialBlock::MaterialBlock(MaterialBlock *parent_, MaterialPart part_, int t, int p, int tu) :
    parent(parent_),
    part(part_),
    technique(t),
    pass(p),
    textureUnit(tu)
{
}

MaterialBlock::~MaterialBlock()
{
    for(uint i=0; i<blocks.Size(); ++i)
        delete blocks[i];
    blocks.Clear();
}

bool MaterialBlock::IsSupported()
{
    return (part != MP_Unsupported);
}

uint MaterialBlock::NumChildren(MaterialPart part) const
{
    uint num = 0;
    foreach(const MaterialBlock *block, blocks)
    {
        if (block->part == part)
            num++;
    }
    return num;
}

uint MaterialBlock::NumTechniques() const
{
    return NumChildren(MP_Technique);
}

uint MaterialBlock::NumPasses() const
{
    return NumChildren(MP_Pass);
}

uint MaterialBlock::NumTextureUnits() const
{
    return NumChildren(MP_TextureUnit);
}

MaterialBlock *MaterialBlock::Technique(uint index) const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_Technique && block->technique == static_cast<int>(index))
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::Pass(uint index) const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_Pass && block->pass == static_cast<int>(index))
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::TextureUnit(uint index) const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_TextureUnit && block->textureUnit == static_cast<int>(index))
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::VertexProgram() const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_VertexProgram)
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::FragmentProgram() const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_FragmentProgram)
            return block;
    }
    return nullptr;
}

uint MaterialBlock::Num(const StringHash &name) const
{
    MaterialProperties::ConstIterator iter = properties.Find(name);
    if (iter != properties.End())
        return iter->second_.Size();
    return 0;
}

bool MaterialBlock::Has(const StringHash &name) const
{
    return (Num(name) > 0);
}

String MaterialBlock::StringValue(const StringHash &name, const String &defaultValue, uint index) const
{
    MaterialProperties::ConstIterator iter = properties.Find(name);
    if (iter != properties.End() && index < iter->second_.Size())
        return iter->second_[index];
    return defaultValue;
}

StringVector MaterialBlock::StringVectorValue(const StringHash &name, uint index) const
{
    String value = StringValue(name, "", index).Trimmed();
    StringVector parts = (!value.Empty() ? value.Split(' ') : StringVector());
    // Remove empty parts to correctly parse "1.0   1.0  1.0 1.0" type of values
    for(auto iter = parts.Begin(); iter != parts.End();)
    {
        *iter = iter->Trimmed();
        if (iter->Empty())
            iter = parts.Erase(iter);
        else
            iter++;
    }
    return parts;
}

Urho3D::Vector2 MaterialBlock::Vector2Value(const StringHash &name, const Urho3D::Vector2 &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 2)
        return Urho3D::Vector2(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]));
    return defaultValue;
}

Urho3D::Vector3 MaterialBlock::Vector3Value(const StringHash &name, const Urho3D::Vector3 &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 3)
        return Urho3D::Vector3(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]), Urho3D::ToFloat(parts[2]));
    return defaultValue;
}

Urho3D::Vector4 MaterialBlock::Vector4Value(const StringHash &name, const Urho3D::Vector4 &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 4)
        return Urho3D::Vector4(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]), Urho3D::ToFloat(parts[2]), Urho3D::ToFloat(parts[3]));
    return defaultValue;
}

Urho3D::Color MaterialBlock::ColorValue(const StringHash &name, const Urho3D::Color &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 3)
    {
        Urho3D::Color color(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]), Urho3D::ToFloat(parts[2]));
        if (parts.Size() >= 4)
            color.a_ = Urho3D::ToFloat(parts[3]);
        return color;
    }
    return defaultValue;
}

bool MaterialBlock::BooleanValue(const StringHash &name, bool defaultValue, uint index) const
{
    String value = StringValue(name, "", index).Trimmed();
    if (value.Compare("on", false) == 0 || value.Compare("enabled", false) == 0 || value.Compare("true", false) == 0 || value.Compare("1", false) == 0)
        return true;
    else if (value.Compare("off", false) == 0 || value.Compare("disabled", false) == 0 || value.Compare("false", false) == 0 || value.Compare("0", false) == 0)
        return false;
    return defaultValue;
}

void MaterialBlock::Dump(bool recursive, uint indentation)
{
    String ind = "";
    while(ind.Length() < indentation) ind += " ";

    LogInfoF("%s%s '%s'", ind.CString(), MaterialPartToString(part).CString(), id.CString());

    indentation += 2;
    while(ind.Length() < indentation) ind += " ";

    for (auto iter = properties.Begin(); iter != properties.End(); ++iter)
    {
        const StringVector &values = iter->second_;
        if (!values.Empty())
        {
            for (uint vi=0; vi<values.Size(); ++vi)
            {
                if (vi == 0)
                    LogInfoF("%s%s '%s'", ind.CString(), PadString(propertyNames[iter->first_], 20).CString(), values[vi].CString());
                else
                    LogInfoF("%s%s '%s'", ind.CString(), propertyNames[iter->first_].CString(), values[vi].CString());
            }
        }
    }

    if (recursive)
    {
        for (auto iter = blocks.Begin(); iter != blocks.End(); ++iter)
            (*iter)->Dump(recursive, indentation);
    }

    indentation -= 2;
    if (indentation == 0)
        LogInfo("");
}

// MaterialParser

MaterialParser::MaterialParser() :
    root(0)
{
}

MaterialParser::~MaterialParser()
{
    SAFE_DELETE(root);
}

String MaterialParser::Error() const
{
    return state.error;
}

bool MaterialParser::Parse(const char *data_, uint lenght_)
{
    data = String(data_, lenght_);
    pos = 0;
    lineNum = 0;

    SAFE_DELETE(root);

    for(;;)
    {
        if (!ProcessLine())
            break;
    }

    // Make root safe even on failure
    if (!root)
        root = new MaterialBlock();

    return (state.error.Length() == 0);
}

void MaterialParser::Advance()
{
    uint endPos = data.Find('\n', pos);
    if (endPos == String::NPOS || endPos < pos)
    {
        pos = String::NPOS;
        return;
    }
    // Empty line with only \n at the start
    else if (endPos == pos)
    {
        pos += 1;
        line = "";
        return;
    }
    line = data.Substring(pos, endPos - pos - (data[endPos-1] == '\r' ? 1 : 0)).Trimmed();
    pos = endPos + 1;
    lineNum++;
}

void MaterialParser::SkipBlock()
{
    uint endPos = data.Find('}', pos);
    if (endPos == String::NPOS || endPos < pos)
    {
        state.error = Urho3D::ToString("Failed to find Block scope end '}', started looking from index %d", pos);
        pos = String::NPOS;
        return;
    }
    // There is a newline after found '}' advance over it.
    pos = endPos + 1;
    Advance();
}

bool IsBlockIndentifier(const StringHash &hash)
{
    return (hash == Material::Block::Material
         || hash == Material::Block::Technique
         || hash == Material::Block::Pass
         || hash == Material::Block::TextureUnit
         || hash == Material::Block::VertexProgram
         || hash == Material::Block::FragmentProgram
         || hash == Material::Block::DefaultParameters);
}

bool MaterialParser::ProcessLine()
{
    // Read next line
    Advance();

    // No more lines?
    if (pos == String::NPOS)
        return false;
    else if (line.Empty())
        return true;

    /*if (lineNum < 10)
        PrintRaw(" " + String(lineNum) + " '" + line + "'\n");
    else
        PrintRaw(String(lineNum) + " '" + line + "'\n");*/

    // Filter comments. Spec only allows single line comments.
    if (line.Length() > 1 && line[0] == '/' && line[1] == '/')
        return true;

    // Block scope end
    if (line[0] == '}')
    {
        // Material not yet started
        if (!state.block)
            return true;

        // Store parsed block to parent
        if (state.block->parent)
            state.block->parent->blocks.Push(state.block);

        // If traversed back to root we are done.
        /// @todo If we want to parse multiple materials from a single file change this logic.
        state.block = state.block->parent;
        return (state.block != 0);
    }
    // Block scope start
    else if (line[0] == '{')
    {
        // Material not yet started
        if (!state.block)
            return true;

        // Skip invalid blocks
        if (!state.block || !state.block->IsSupported())
            SkipBlock();
        return true;
    }

    // Split to "<key> <value>" from the first space.
    // Note that value can contain spaces, it is stored as is.
    uint splitPos = line.Find(' ');
    String keyStr = (splitPos == String::NPOS ? line : line.Substring(0, splitPos).ToLower());
    StringHash key(keyStr);
    String value = (splitPos == String::NPOS ? "" : line.Substring(splitPos+1));

    // Do not begin default_params block if material not started yet
    if (key == Material::Block::DefaultParameters && !state.block)
        return true;

    // Is this a new block scope identifier?
    if (IsBlockIndentifier(key))
    {
        MaterialPart part = MP_Unsupported;

        // Detect block type
        if (key == Material::Block::Material)
        {
            /// @todo http://www.ogre3d.org/docs/manual/manual_25.html#Script-Inheritance
            part = MP_Material;
            state.technique = -1;
            state.pass = -1;
            state.textureUnit = -1;
        }
        else if (key == Material::Block::Technique)
        {
            part = MP_Technique;
            state.technique++;
            state.pass = -1;
            state.textureUnit = -1;
        }
        else if (key == Material::Block::Pass)
        {
            part = MP_Pass;
            state.pass++;
            state.textureUnit = -1;
        }
        else if (key == Material::Block::TextureUnit)
        {
            part = MP_TextureUnit;
            state.textureUnit++;
        }
        else if (key == Material::Block::VertexProgram)
            part = MP_VertexProgram;
        else if (key == Material::Block::FragmentProgram)
            part = MP_FragmentProgram;
        else if (key == Material::Block::DefaultParameters)
            part = MP_DefaultParameters;

        state.block = new MaterialBlock(state.block, part, state.technique, state.pass, state.textureUnit);
        state.block->id = value;

        if (!root && part == MP_Material)
            root = state.block;

        //LogInfoF("    tech %d pass %d tu %d", state.block->technique, state.block->pass, state.block->textureUnit);
        return true;
    }
    else if (value.Empty())
    {
        LogWarningF("Ogre::MaterialParser: Invalid script token '%s' without a value on line %d before column %d", keyStr.CString(), lineNum, pos);
        return true;
    }
    // Material not yet started
    if (!state.block)
        return true;

    // Add property to current block
    state.block->propertyNames[key] = keyStr;
    state.block->properties[key].Push(value);
    return true;
}

}

}
<commit_msg>MaterialParser: Clarify in warning message that we are only skipping this one invalid token.<commit_after>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "OgreMaterialDefines.h"
#include "CoreStringUtils.h"
#include "LoggingFunctions.h"

#include <Engine/Core/StringUtils.h>

namespace Tundra
{

namespace Ogre
{

// MaterialBlock

MaterialBlock::MaterialBlock(MaterialBlock *parent_, MaterialPart part_, int t, int p, int tu) :
    parent(parent_),
    part(part_),
    technique(t),
    pass(p),
    textureUnit(tu)
{
}

MaterialBlock::~MaterialBlock()
{
    for(uint i=0; i<blocks.Size(); ++i)
        delete blocks[i];
    blocks.Clear();
}

bool MaterialBlock::IsSupported()
{
    return (part != MP_Unsupported);
}

uint MaterialBlock::NumChildren(MaterialPart part) const
{
    uint num = 0;
    foreach(const MaterialBlock *block, blocks)
    {
        if (block->part == part)
            num++;
    }
    return num;
}

uint MaterialBlock::NumTechniques() const
{
    return NumChildren(MP_Technique);
}

uint MaterialBlock::NumPasses() const
{
    return NumChildren(MP_Pass);
}

uint MaterialBlock::NumTextureUnits() const
{
    return NumChildren(MP_TextureUnit);
}

MaterialBlock *MaterialBlock::Technique(uint index) const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_Technique && block->technique == static_cast<int>(index))
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::Pass(uint index) const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_Pass && block->pass == static_cast<int>(index))
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::TextureUnit(uint index) const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_TextureUnit && block->textureUnit == static_cast<int>(index))
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::VertexProgram() const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_VertexProgram)
            return block;
    }
    return nullptr;
}

MaterialBlock *MaterialBlock::FragmentProgram() const
{
    foreach(MaterialBlock *block, blocks)
    {
        if (block->part == MP_FragmentProgram)
            return block;
    }
    return nullptr;
}

uint MaterialBlock::Num(const StringHash &name) const
{
    MaterialProperties::ConstIterator iter = properties.Find(name);
    if (iter != properties.End())
        return iter->second_.Size();
    return 0;
}

bool MaterialBlock::Has(const StringHash &name) const
{
    return (Num(name) > 0);
}

String MaterialBlock::StringValue(const StringHash &name, const String &defaultValue, uint index) const
{
    MaterialProperties::ConstIterator iter = properties.Find(name);
    if (iter != properties.End() && index < iter->second_.Size())
        return iter->second_[index];
    return defaultValue;
}

StringVector MaterialBlock::StringVectorValue(const StringHash &name, uint index) const
{
    String value = StringValue(name, "", index).Trimmed();
    StringVector parts = (!value.Empty() ? value.Split(' ') : StringVector());
    // Remove empty parts to correctly parse "1.0   1.0  1.0 1.0" type of values
    for(auto iter = parts.Begin(); iter != parts.End();)
    {
        *iter = iter->Trimmed();
        if (iter->Empty())
            iter = parts.Erase(iter);
        else
            iter++;
    }
    return parts;
}

Urho3D::Vector2 MaterialBlock::Vector2Value(const StringHash &name, const Urho3D::Vector2 &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 2)
        return Urho3D::Vector2(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]));
    return defaultValue;
}

Urho3D::Vector3 MaterialBlock::Vector3Value(const StringHash &name, const Urho3D::Vector3 &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 3)
        return Urho3D::Vector3(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]), Urho3D::ToFloat(parts[2]));
    return defaultValue;
}

Urho3D::Vector4 MaterialBlock::Vector4Value(const StringHash &name, const Urho3D::Vector4 &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 4)
        return Urho3D::Vector4(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]), Urho3D::ToFloat(parts[2]), Urho3D::ToFloat(parts[3]));
    return defaultValue;
}

Urho3D::Color MaterialBlock::ColorValue(const StringHash &name, const Urho3D::Color &defaultValue, uint index) const
{
    StringVector parts = StringVectorValue(name, index);
    if (parts.Size() >= 3)
    {
        Urho3D::Color color(Urho3D::ToFloat(parts[0]), Urho3D::ToFloat(parts[1]), Urho3D::ToFloat(parts[2]));
        if (parts.Size() >= 4)
            color.a_ = Urho3D::ToFloat(parts[3]);
        return color;
    }
    return defaultValue;
}

bool MaterialBlock::BooleanValue(const StringHash &name, bool defaultValue, uint index) const
{
    String value = StringValue(name, "", index).Trimmed();
    if (value.Compare("on", false) == 0 || value.Compare("enabled", false) == 0 || value.Compare("true", false) == 0 || value.Compare("1", false) == 0)
        return true;
    else if (value.Compare("off", false) == 0 || value.Compare("disabled", false) == 0 || value.Compare("false", false) == 0 || value.Compare("0", false) == 0)
        return false;
    return defaultValue;
}

void MaterialBlock::Dump(bool recursive, uint indentation)
{
    String ind = "";
    while(ind.Length() < indentation) ind += " ";

    LogInfoF("%s%s '%s'", ind.CString(), MaterialPartToString(part).CString(), id.CString());

    indentation += 2;
    while(ind.Length() < indentation) ind += " ";

    for (auto iter = properties.Begin(); iter != properties.End(); ++iter)
    {
        const StringVector &values = iter->second_;
        if (!values.Empty())
        {
            for (uint vi=0; vi<values.Size(); ++vi)
            {
                if (vi == 0)
                    LogInfoF("%s%s '%s'", ind.CString(), PadString(propertyNames[iter->first_], 20).CString(), values[vi].CString());
                else
                    LogInfoF("%s%s '%s'", ind.CString(), propertyNames[iter->first_].CString(), values[vi].CString());
            }
        }
    }

    if (recursive)
    {
        for (auto iter = blocks.Begin(); iter != blocks.End(); ++iter)
            (*iter)->Dump(recursive, indentation);
    }

    indentation -= 2;
    if (indentation == 0)
        LogInfo("");
}

// MaterialParser

MaterialParser::MaterialParser() :
    root(0)
{
}

MaterialParser::~MaterialParser()
{
    SAFE_DELETE(root);
}

String MaterialParser::Error() const
{
    return state.error;
}

bool MaterialParser::Parse(const char *data_, uint lenght_)
{
    data = String(data_, lenght_);
    pos = 0;
    lineNum = 0;

    SAFE_DELETE(root);

    for(;;)
    {
        if (!ProcessLine())
            break;
    }

    // Make root safe even on failure
    if (!root)
        root = new MaterialBlock();

    return (state.error.Length() == 0);
}

void MaterialParser::Advance()
{
    uint endPos = data.Find('\n', pos);
    if (endPos == String::NPOS || endPos < pos)
    {
        pos = String::NPOS;
        return;
    }
    // Empty line with only \n at the start
    else if (endPos == pos)
    {
        pos += 1;
        line = "";
        return;
    }
    line = data.Substring(pos, endPos - pos - (data[endPos-1] == '\r' ? 1 : 0)).Trimmed();
    pos = endPos + 1;
    lineNum++;
}

void MaterialParser::SkipBlock()
{
    uint endPos = data.Find('}', pos);
    if (endPos == String::NPOS || endPos < pos)
    {
        state.error = Urho3D::ToString("Failed to find Block scope end '}', started looking from index %d", pos);
        pos = String::NPOS;
        return;
    }
    // There is a newline after found '}' advance over it.
    pos = endPos + 1;
    Advance();
}

bool IsBlockIndentifier(const StringHash &hash)
{
    return (hash == Material::Block::Material
         || hash == Material::Block::Technique
         || hash == Material::Block::Pass
         || hash == Material::Block::TextureUnit
         || hash == Material::Block::VertexProgram
         || hash == Material::Block::FragmentProgram
         || hash == Material::Block::DefaultParameters);
}

bool MaterialParser::ProcessLine()
{
    // Read next line
    Advance();

    // No more lines?
    if (pos == String::NPOS)
        return false;
    else if (line.Empty())
        return true;

    /*if (lineNum < 10)
        PrintRaw(" " + String(lineNum) + " '" + line + "'\n");
    else
        PrintRaw(String(lineNum) + " '" + line + "'\n");*/

    // Filter comments. Spec only allows single line comments.
    if (line.Length() > 1 && line[0] == '/' && line[1] == '/')
        return true;

    // Block scope end
    if (line[0] == '}')
    {
        // Material not yet started
        if (!state.block)
            return true;

        // Store parsed block to parent
        if (state.block->parent)
            state.block->parent->blocks.Push(state.block);

        // If traversed back to root we are done.
        /// @todo If we want to parse multiple materials from a single file change this logic.
        state.block = state.block->parent;
        return (state.block != 0);
    }
    // Block scope start
    else if (line[0] == '{')
    {
        // Material not yet started
        if (!state.block)
            return true;

        // Skip invalid blocks
        if (!state.block || !state.block->IsSupported())
            SkipBlock();
        return true;
    }

    // Split to "<key> <value>" from the first space.
    // Note that value can contain spaces, it is stored as is.
    uint splitPos = line.Find(' ');
    String keyStr = (splitPos == String::NPOS ? line : line.Substring(0, splitPos).ToLower());
    StringHash key(keyStr);
    String value = (splitPos == String::NPOS ? "" : line.Substring(splitPos+1));

    // Do not begin default_params block if material not started yet
    if (key == Material::Block::DefaultParameters && !state.block)
        return true;

    // Is this a new block scope identifier?
    if (IsBlockIndentifier(key))
    {
        MaterialPart part = MP_Unsupported;

        // Detect block type
        if (key == Material::Block::Material)
        {
            /// @todo http://www.ogre3d.org/docs/manual/manual_25.html#Script-Inheritance
            part = MP_Material;
            state.technique = -1;
            state.pass = -1;
            state.textureUnit = -1;
        }
        else if (key == Material::Block::Technique)
        {
            part = MP_Technique;
            state.technique++;
            state.pass = -1;
            state.textureUnit = -1;
        }
        else if (key == Material::Block::Pass)
        {
            part = MP_Pass;
            state.pass++;
            state.textureUnit = -1;
        }
        else if (key == Material::Block::TextureUnit)
        {
            part = MP_TextureUnit;
            state.textureUnit++;
        }
        else if (key == Material::Block::VertexProgram)
            part = MP_VertexProgram;
        else if (key == Material::Block::FragmentProgram)
            part = MP_FragmentProgram;
        else if (key == Material::Block::DefaultParameters)
            part = MP_DefaultParameters;

        state.block = new MaterialBlock(state.block, part, state.technique, state.pass, state.textureUnit);
        state.block->id = value;

        if (!root && part == MP_Material)
            root = state.block;

        //LogInfoF("    tech %d pass %d tu %d", state.block->technique, state.block->pass, state.block->textureUnit);
        return true;
    }
    else if (value.Empty())
    {
        LogWarningF("Ogre::MaterialParser: Skipping invalid script token '%s' without a value on line %d before column %d", keyStr.CString(), lineNum, pos);
        return true;
    }
    // Material not yet started
    if (!state.block)
        return true;

    // Add property to current block
    state.block->propertyNames[key] = keyStr;
    state.block->properties[key].Push(value);
    return true;
}

}

}
<|endoftext|>


<commit_before>#include <GG/EveLayout.h>

#include <GG/EveParser.h>
#include <GG/GUI.h>
#include <GG/Timer.h>
#include <GG/Wnd.h>
#include <GG/SDL/SDLGUI.h>
#include <GG/adobe/adam.hpp>

#include <boost/filesystem.hpp>

#include <fstream>

#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>

#include "TestingUtils.h"

const char* g_input_file = 0;
const char* g_output_dir = 0;
bool g_dont_exit = false;

struct StopDialog
{
    StopDialog(GG::Wnd* dialog, const std::string& output) :
        m_dialog(dialog),
        m_output(output)
        {}
    void operator()(unsigned int, GG::Timer*)
        {
            GG::GUI::GetGUI()->SaveWndAsPNG(m_dialog, m_output);
            m_dialog->EndRun();
        }
    GG::Wnd* m_dialog;
    std::string m_output;
};

class MinimalGGApp : public GG::SDLGUI
{
public:
    MinimalGGApp();

    virtual void Enter2DMode();
    virtual void Exit2DMode();

private:
    virtual void GLInit();
    virtual void Initialize();
    virtual void FinalCleanup();
};

MinimalGGApp::MinimalGGApp() :
    SDLGUI(1024, 768, false, "Minimal GG App")
{}

void MinimalGGApp::Enter2DMode()
{
    glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_TEXTURE_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_CULL_FACE);
    glEnable(GL_TEXTURE_2D);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glViewport(0, 0, Value(AppWidth()), Value(AppHeight()));

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    glOrtho(0.0, Value(AppWidth()), Value(AppHeight()), 0.0, 0.0, Value(AppWidth()));

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
}

void MinimalGGApp::Exit2DMode()
{
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glPopAttrib();
}

void MinimalGGApp::GLInit()
{
    double ratio = Value(AppWidth() * 1.0) / Value(AppHeight());

    glEnable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glClearColor(0, 0, 0, 0);
    glViewport(0, 0, Value(AppWidth()), Value(AppHeight()));
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(50.0, ratio, 1.0, 10.0);
    gluLookAt(0.0, 0.0, 5.0,
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
    glMatrixMode(GL_MODELVIEW);
}

void MinimalGGApp::Initialize()
{
    adobe::sheet_t sheet;
    GG::EveLayout layout(sheet);
    adobe::eve_callback_suite_t callbacks = layout.BindCallbacks();
    std::string file_contents = read_file(g_input_file);
    GG::Wnd* w = 0;
    if (GG::Parse(file_contents, g_input_file, w, callbacks)) {
        GG::Wnd& eve_dialog = layout.Finish();
        boost::filesystem::path input(g_input_file);
        boost::filesystem::path output(g_output_dir);
#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION == 3
        output /= input.stem().native() + ".png";
#else
        output /= input.stem() + ".png";
#endif
        GG::Timer timer(100);
        if (!g_dont_exit)
            GG::Connect(timer.FiredSignal, StopDialog(&eve_dialog, output.string()));
        eve_dialog.Run();
    }
    Exit(0);
}

void MinimalGGApp::FinalCleanup()
{}

BOOST_AUTO_TEST_CASE( eve_layout )
{
    MinimalGGApp app;
    app();
}

// Most of this is boilerplate cut-and-pasted from Boost.Test.  We need to
// select which test(s) to do, so we can't use it here unmodified.

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
bool init_unit_test()                   {
#else
::boost::unit_test::test_suite*
init_unit_test_suite( int, char* [] )   {
#endif

#ifdef BOOST_TEST_MODULE
    using namespace ::boost::unit_test;
    assign_op( framework::master_test_suite().p_name.value, BOOST_TEST_STRINGIZE( BOOST_TEST_MODULE ).trim( "\"" ), 0 );

#endif

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
    return true;
}
#else
    return 0;
}
#endif

int BOOST_TEST_CALL_DECL
main( int argc, char* argv[] )
{
    g_input_file = argv[1];
    g_output_dir = argv[2];
    if (argc == 4)
        g_dont_exit = true;
    return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv );
}
<commit_msg>Changed Eve layout test to use GG::MakeDialog() instead of EveLayout.<commit_after>#include <GG/EveLayout.h>

#include <GG/EveGlue.h>
#include <GG/EveParser.h>
#include <GG/GUI.h>
#include <GG/Timer.h>
#include <GG/Wnd.h>
#include <GG/SDL/SDLGUI.h>
#include <GG/adobe/adam.hpp>

#include <boost/filesystem.hpp>

#include <fstream>

#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>

#include "TestingUtils.h"

const char* g_input_file = 0;
const char* g_output_dir = 0;
bool g_dont_exit = false;

struct StopDialog
{
    StopDialog(GG::Wnd* dialog, const std::string& output) :
        m_dialog(dialog),
        m_output(output)
        {}
    void operator()(unsigned int, GG::Timer*)
        {
            GG::GUI::GetGUI()->SaveWndAsPNG(m_dialog, m_output);
            m_dialog->EndRun();
        }
    GG::Wnd* m_dialog;
    std::string m_output;
};

class MinimalGGApp : public GG::SDLGUI
{
public:
    MinimalGGApp();

    virtual void Enter2DMode();
    virtual void Exit2DMode();

private:
    virtual void GLInit();
    virtual void Initialize();
    virtual void FinalCleanup();
};

MinimalGGApp::MinimalGGApp() :
    SDLGUI(1024, 768, false, "Minimal GG App")
{}

void MinimalGGApp::Enter2DMode()
{
    glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_TEXTURE_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_CULL_FACE);
    glEnable(GL_TEXTURE_2D);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glViewport(0, 0, Value(AppWidth()), Value(AppHeight()));

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    glOrtho(0.0, Value(AppWidth()), Value(AppHeight()), 0.0, 0.0, Value(AppWidth()));

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
}

void MinimalGGApp::Exit2DMode()
{
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glPopAttrib();
}

void MinimalGGApp::GLInit()
{
    double ratio = Value(AppWidth() * 1.0) / Value(AppHeight());

    glEnable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glClearColor(0, 0, 0, 0);
    glViewport(0, 0, Value(AppWidth()), Value(AppHeight()));
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(50.0, ratio, 1.0, 10.0);
    gluLookAt(0.0, 0.0, 5.0,
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
    glMatrixMode(GL_MODELVIEW);
}

bool OkHandler(adobe::name_t name, const adobe::any_regular_t&)
{ return name == adobe::static_name_t("ok"); }

void MinimalGGApp::Initialize()
{
    std::ifstream eve(g_input_file);
    std::istringstream adam("sheet foo\n"
                            "{\n"
                            "output:\n"
                            "    result <== { foo: 42 };\n"
                            "}");
    GG::Wnd* eve_dialog = GG::MakeDialog(eve, adam, &OkHandler);

    boost::filesystem::path input(g_input_file);
    boost::filesystem::path output(g_output_dir);
#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION == 3
    output /= input.stem().native() + ".png";
#else
    output /= input.stem() + ".png";
#endif
    GG::Timer timer(100);
    if (!g_dont_exit)
        GG::Connect(timer.FiredSignal, StopDialog(eve_dialog, output.string()));
    eve_dialog->Run();

    Exit(0);
}

void MinimalGGApp::FinalCleanup()
{}

BOOST_AUTO_TEST_CASE( eve_layout )
{
    MinimalGGApp app;
    app();
}

// Most of this is boilerplate cut-and-pasted from Boost.Test.  We need to
// select which test(s) to do, so we can't use it here unmodified.

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
bool init_unit_test()                   {
#else
::boost::unit_test::test_suite*
init_unit_test_suite( int, char* [] )   {
#endif

#ifdef BOOST_TEST_MODULE
    using namespace ::boost::unit_test;
    assign_op( framework::master_test_suite().p_name.value, BOOST_TEST_STRINGIZE( BOOST_TEST_MODULE ).trim( "\"" ), 0 );

#endif

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
    return true;
}
#else
    return 0;
}
#endif

int BOOST_TEST_CALL_DECL
main( int argc, char* argv[] )
{
    g_input_file = argv[1];
    g_output_dir = argv[2];
    if (argc == 4)
        g_dont_exit = true;
    return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv );
}
<|endoftext|>


<commit_before>#ifndef ITER_ACCUMULATE_H_
#define ITER_ACCUMULATE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <functional>
#include <iterator>
#include <optional>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container, typename AccumulateFunc>
    class Accumulator;

    using AccumulateFn = IterToolFnOptionalBindSecond<Accumulator, std::plus<>>;
  }
  constexpr impl::AccumulateFn accumulate{};
}

template <typename Container, typename AccumulateFunc>
class iter::impl::Accumulator {
 private:
  Container container_;
  mutable AccumulateFunc accumulate_func_;

  friend AccumulateFn;

  using AccumVal = std::remove_reference_t<std::result_of_t<AccumulateFunc(
      iterator_deref<Container>, iterator_deref<Container>)>>;

  Accumulator(Container&& container, AccumulateFunc accumulate_func)
      : container_(std::forward<Container>(container)),
        accumulate_func_(accumulate_func) {}

 public:
  Accumulator(Accumulator&&) = default;

  template <typename ContainerT>
  class Iterator {
   private:
    template <typename>
    friend class Iterator;
    IteratorWrapper<ContainerT> sub_iter_;
    IteratorWrapper<ContainerT> sub_end_;
    AccumulateFunc* accumulate_func_;
    std::optional<AccumVal> acc_val_;

   public:
    using iterator_category = std::input_iterator_tag;
    using value_type = AccumVal;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    Iterator(IteratorWrapper<ContainerT>&& sub_iter,
        IteratorWrapper<ContainerT>&& sub_end, AccumulateFunc& accumulate_fun)
        : sub_iter_{std::move(sub_iter)},
          sub_end_{std::move(sub_end)},
          accumulate_func_(&accumulate_fun),
          // only get first value if not an end iterator
          acc_val_{!(sub_iter_ != sub_end_)
                       ? std::nullopt
                       : std::make_optional<AccumVal>(*sub_iter_)} {}

    const AccumVal& operator*() const {
      return *acc_val_;
    }

    const AccumVal* operator->() const {
      return &*acc_val_;
    }

    Iterator& operator++() {
      ++sub_iter_;
      if (sub_iter_ != sub_end_) {
        *acc_val_ = (*accumulate_func_)(*acc_val_, *sub_iter_);
      }
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    template <typename T>
    bool operator!=(const Iterator<T>& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    template <typename T>
    bool operator==(const Iterator<T>& other) const {
      return !(*this != other);
    }
  };

  Iterator<Container> begin() {
    return {get_begin(container_), get_end(container_), accumulate_func_};
  }

  Iterator<Container> end() {
    return {get_end(container_), get_end(container_), accumulate_func_};
  }
  Iterator<AsConst<Container>> begin() const {
    return {get_begin(std::as_const(container_)),
        get_end(std::as_const(container_)), accumulate_func_};
  }

  Iterator<AsConst<Container>> end() const {
    return {get_end(std::as_const(container_)),
        get_end(std::as_const(container_)), accumulate_func_};
  }
};

#endif
<commit_msg>Uses std::invoke in accumulate<commit_after>#ifndef ITER_ACCUMULATE_H_
#define ITER_ACCUMULATE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <functional>
#include <iterator>
#include <optional>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container, typename AccumulateFunc>
    class Accumulator;

    using AccumulateFn = IterToolFnOptionalBindSecond<Accumulator, std::plus<>>;
  }
  constexpr impl::AccumulateFn accumulate{};
}

template <typename Container, typename AccumulateFunc>
class iter::impl::Accumulator {
 private:
  Container container_;
  mutable AccumulateFunc accumulate_func_;

  friend AccumulateFn;

  using AccumVal = std::remove_reference_t<std::result_of_t<AccumulateFunc(
      iterator_deref<Container>, iterator_deref<Container>)>>;

  Accumulator(Container&& container, AccumulateFunc accumulate_func)
      : container_(std::forward<Container>(container)),
        accumulate_func_(accumulate_func) {}

 public:
  Accumulator(Accumulator&&) = default;

  template <typename ContainerT>
  class Iterator {
   private:
    template <typename>
    friend class Iterator;
    IteratorWrapper<ContainerT> sub_iter_;
    IteratorWrapper<ContainerT> sub_end_;
    AccumulateFunc* accumulate_func_;
    std::optional<AccumVal> acc_val_;

   public:
    using iterator_category = std::input_iterator_tag;
    using value_type = AccumVal;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    Iterator(IteratorWrapper<ContainerT>&& sub_iter,
        IteratorWrapper<ContainerT>&& sub_end, AccumulateFunc& accumulate_fun)
        : sub_iter_{std::move(sub_iter)},
          sub_end_{std::move(sub_end)},
          accumulate_func_(&accumulate_fun),
          // only get first value if not an end iterator
          acc_val_{!(sub_iter_ != sub_end_)
                       ? std::nullopt
                       : std::make_optional<AccumVal>(*sub_iter_)} {}

    const AccumVal& operator*() const {
      return *acc_val_;
    }

    const AccumVal* operator->() const {
      return &*acc_val_;
    }

    Iterator& operator++() {
      ++sub_iter_;
      if (sub_iter_ != sub_end_) {
        *acc_val_ = std::invoke(*accumulate_func_, *acc_val_, *sub_iter_);
      }
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    template <typename T>
    bool operator!=(const Iterator<T>& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    template <typename T>
    bool operator==(const Iterator<T>& other) const {
      return !(*this != other);
    }
  };

  Iterator<Container> begin() {
    return {get_begin(container_), get_end(container_), accumulate_func_};
  }

  Iterator<Container> end() {
    return {get_end(container_), get_end(container_), accumulate_func_};
  }
  Iterator<AsConst<Container>> begin() const {
    return {get_begin(std::as_const(container_)),
        get_end(std::as_const(container_)), accumulate_func_};
  }

  Iterator<AsConst<Container>> end() const {
    return {get_end(std::as_const(container_)),
        get_end(std::as_const(container_)), accumulate_func_};
  }
};

#endif
<|endoftext|>


<commit_before>/**
 * These codes are licensed under the Unlicense.
 * http://unlicense.org
 */

#ifndef FURFURYLIC_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7
#define FURFURYLIC_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <limits>
#include <memory>
#include <ostream>
#include <sstream>
#include <streambuf>
#include <string>
#include <type_traits>
#include <utility>

#include "formatted_output.hpp"

namespace furfurylic {
namespace commata {
namespace detail {

template <class T>
struct npos_impl
{
    constexpr static T npos = static_cast<T>(-1);
};

// To define this in a header, npos_impl is a template
template <class T>
constexpr T npos_impl<T>::npos;

} // end namespace detail

class text_error;

class text_error_info
{
    const text_error* ex_;

public:
    explicit text_error_info(const text_error& ex) noexcept :
        ex_(&ex)
    {}

    text_error_info(const text_error_info& ex) noexcept = default;
    text_error_info& operator=(const text_error_info& ex) noexcept = default;

    const text_error& error() const noexcept
    {
        return *ex_;
    }
};

class text_error :
    public std::exception, public detail::npos_impl<std::size_t>
{
    std::shared_ptr<std::string> what_;
    std::pair<std::size_t, std::size_t> physical_position_;

public:
    template <class T,
        class = std::enable_if_t<std::is_constructible<std::string, T>::value>>
    explicit text_error(T&& what_arg) :
        what_(std::make_shared<std::string>(std::forward<T>(what_arg))),
        physical_position_(npos, npos)
    {}

    // Copy/move ctors and copy/move assignment ops are explicitly defined
    // so that they are noexcept

    text_error(const text_error& other) noexcept :
        std::exception(other),
        what_(other.what_),
        physical_position_(other.physical_position_)
        // According to C++14 20.3.2 (1), pair's copy ctor is noexcept
    {}

    text_error(text_error&& other) noexcept :
        std::exception(std::move(other)),
        what_(std::move(other.what_)),
        physical_position_(other.physical_position_)
        // ditto
    {}

    text_error& operator=(const text_error& other) noexcept
    {
        std::exception::operator=(other);
        what_ = other.what_;
        physical_position_ = other.physical_position_;
        // According to C++14 20.3.2 (1), pair's assignments are noexcept
        return *this;
    }

    text_error& operator=(text_error&& other) noexcept
    {
        std::exception::operator=(std::move(other));
        what_ = std::move(other.what_);
        physical_position_ = other.physical_position_;
        // ditto
        return *this;
    }

    const char* what() const noexcept override
    {
        return what_->c_str(); // std::string::c_str is noexcept
    }

    void set_physical_position(std::size_t line = npos, std::size_t col = npos)
    {
        physical_position_ = std::make_pair(line, col);
    }

    const std::pair<std::size_t, std::size_t>* get_physical_position() const
        noexcept
    {
        // std::make_pair<std::size_t, std::size_t> shall not throw exceptions
        return (physical_position_ != std::make_pair(npos, npos)) ?
            &physical_position_ : nullptr;
    }

    text_error_info info() const noexcept
    {
        return text_error_info(*this);
    }
};

namespace detail {

// Prints a non-negative integer value in the decimal system
// into a sufficient-length buffer
template <std::size_t N>
std::streamsize print_pos(char (&s)[N], std::size_t pos)
{
    const auto len = (pos != text_error::npos) ?
        std::snprintf(s, N, "%zu", pos + 1) :
        std::snprintf(s, N, "n/a");
    assert((len > 0 ) && (static_cast<std::size_t>(len) < N));
    return static_cast<std::streamsize>(len);
}

template <std::size_t N>
std::streamsize print_pos(wchar_t (&s)[N], std::size_t pos)
{
    const auto len = (pos != text_error::npos) ?
        std::swprintf(s, N, L"%zu", pos + 1) :
        std::swprintf(s, N, L"n/a");
    assert((len > 0 ) && (static_cast<std::size_t>(len) < N));
    return static_cast<std::streamsize>(len);
}

} // end namespace detail

template <class Tr>
std::basic_ostream<char, Tr>& operator<<(
    std::basic_ostream<char, Tr>& os, const text_error_info& i)
{
    if (const auto p = i.error().get_physical_position()) {
        // line
        char l[std::numeric_limits<std::size_t>::digits10 + 2];
        const auto l_len = detail::print_pos(l, p->first);

        // column
        char c[sizeof(l)];
        const auto c_len = detail::print_pos(c, p->second);

        // what
        const auto w = i.error().what();
        const auto w_len = static_cast<std::streamsize>(std::strlen(w));

        const auto n = w_len + l_len + c_len + ((w_len > 0) ? 15 : 27);

        return detail::formatted_output(os, n,
            [w, w_len, l = &l[0], l_len, c = &c[0], c_len]
            (auto* sb) {
                if (w_len > 0) {
                    if ((sb->sputn(w, w_len) != w_len)
                     || (sb->sputn("; line ", 7) != 7)) {
                        return false;
                    }
                } else if (sb->sputn("Text error at line ", 19) != 19) {
                    return false;
                }
                return (sb->sputn(l, l_len) == l_len)
                    && (sb->sputn(" column ", 8) == 8)
                    && (sb->sputn(c, c_len) == c_len);
            });

    } else {
        return os << i.error().what();
    }
}

template <class Tr>
std::basic_ostream<wchar_t, Tr>& operator<<(
    std::basic_ostream<wchar_t, Tr>& os, const text_error_info& i)
{
    // Count the wide characters in what, which may be an NTMBS
    auto w_raw = i.error().what();
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif
    auto w_len = static_cast<std::streamsize>(std::mbstowcs(0, w_raw, 0));
#ifdef _MSC_VER
#pragma warning(pop)
#endif
    if (w_len == -1) {
        // Conversion failed
        w_raw = "";
        w_len = 0;
    }

    if (const auto p = i.error().get_physical_position()) {
        // line
        wchar_t l[std::numeric_limits<std::size_t>::digits10 + 2];
        const auto l_len = detail::print_pos(l, p->first);

        // column
        wchar_t c[sizeof(l)];
        const auto c_len = detail::print_pos(c, p->second);

        const auto n = w_len + l_len + c_len + ((w_len > 0) ? 15 : 27);

        return detail::formatted_output(os, n,
            [w_raw, w_len, l = &l[0], l_len, c = &c[0], c_len]
            (auto* sb) {
                if (w_len > 0) {
                    std::unique_ptr<wchar_t[]> w(
                        new wchar_t[w_len + 1]);                    // throw
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif
                    std::mbstowcs(w.get(), w_raw, w_len);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
                    w[w_len] = L'\0';   // maybe not required
                    if ((sb->sputn(w.get(), w_len) != w_len)
                     || (sb->sputn(L"; line ", 7) != 7)) {
                        return false;
                    }
                } else if (sb->sputn(L"Text error at line ", 19) != 19) {
                    return false;
                }
                return (sb->sputn(l, l_len) == l_len)
                    && (sb->sputn(L" column ", 8) == 8)
                    && (sb->sputn(c, c_len) == c_len);
            });

    } else if (w_len > 0) {
        return detail::formatted_output(os, w_len,
            [w_raw, &w_len]
            (auto* sb) {
                std::unique_ptr<wchar_t[]> w(
                    new wchar_t[w_len + 1]);                        // throw
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif
                std::mbstowcs(w.get(), w_raw, w_len);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
                w[w_len] = L'\0';   // maybe not required
                return sb->sputn(w.get(), w_len) == w_len;
            });

    } else {
        return os;
    }
}

inline std::string to_string(const text_error_info& i)
{
    std::ostringstream s;
    s << i;
    return s.str();
}

inline std::wstring to_wstring(const text_error_info& i)
{
    std::wostringstream s;
    s << i;
    return s.str();
}

}}

#endif
<commit_msg>Make text_error have a "fluent interface"<commit_after>/**
 * These codes are licensed under the Unlicense.
 * http://unlicense.org
 */

#ifndef FURFURYLIC_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7
#define FURFURYLIC_GUARD_E8F031F6_10D8_4585_9012_CFADC2F95BA7

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <limits>
#include <memory>
#include <ostream>
#include <sstream>
#include <streambuf>
#include <string>
#include <type_traits>
#include <utility>

#include "formatted_output.hpp"

namespace furfurylic {
namespace commata {
namespace detail {

template <class T>
struct npos_impl
{
    constexpr static T npos = static_cast<T>(-1);
};

// To define this in a header, npos_impl is a template
template <class T>
constexpr T npos_impl<T>::npos;

} // end namespace detail

class text_error;

class text_error_info
{
    const text_error* ex_;

public:
    explicit text_error_info(const text_error& ex) noexcept :
        ex_(&ex)
    {}

    text_error_info(const text_error_info& ex) noexcept = default;
    text_error_info& operator=(const text_error_info& ex) noexcept = default;

    const text_error& error() const noexcept
    {
        return *ex_;
    }
};

class text_error :
    public std::exception, public detail::npos_impl<std::size_t>
{
    std::shared_ptr<std::string> what_;
    std::pair<std::size_t, std::size_t> physical_position_;

public:
    template <class T,
        class = std::enable_if_t<std::is_constructible<std::string, T>::value>>
    explicit text_error(T&& what_arg) :
        what_(std::make_shared<std::string>(std::forward<T>(what_arg))),
        physical_position_(npos, npos)
    {}

    // Copy/move ctors and copy/move assignment ops are explicitly defined
    // so that they are noexcept

    text_error(const text_error& other) noexcept :
        std::exception(other),
        what_(other.what_),
        physical_position_(other.physical_position_)
        // According to C++14 20.3.2 (1), pair's copy ctor is noexcept
    {}

    text_error(text_error&& other) noexcept :
        std::exception(std::move(other)),
        what_(std::move(other.what_)),
        physical_position_(other.physical_position_)
        // ditto
    {}

    text_error& operator=(const text_error& other) noexcept
    {
        std::exception::operator=(other);
        what_ = other.what_;
        physical_position_ = other.physical_position_;
        // According to C++14 20.3.2 (1), pair's assignments are noexcept
        return *this;
    }

    text_error& operator=(text_error&& other) noexcept
    {
        std::exception::operator=(std::move(other));
        what_ = std::move(other.what_);
        physical_position_ = other.physical_position_;
        // ditto
        return *this;
    }

    const char* what() const noexcept override
    {
        return what_->c_str(); // std::string::c_str is noexcept
    }

    text_error& set_physical_position(
        std::size_t line = npos, std::size_t col = npos)
    {
        physical_position_ = std::make_pair(line, col);
        return *this;
    }

    const std::pair<std::size_t, std::size_t>* get_physical_position() const
        noexcept
    {
        // std::make_pair<std::size_t, std::size_t> shall not throw exceptions
        return (physical_position_ != std::make_pair(npos, npos)) ?
            &physical_position_ : nullptr;
    }

    text_error_info info() const noexcept
    {
        return text_error_info(*this);
    }
};

namespace detail {

// Prints a non-negative integer value in the decimal system
// into a sufficient-length buffer
template <std::size_t N>
std::streamsize print_pos(char (&s)[N], std::size_t pos)
{
    const auto len = (pos != text_error::npos) ?
        std::snprintf(s, N, "%zu", pos + 1) :
        std::snprintf(s, N, "n/a");
    assert((len > 0 ) && (static_cast<std::size_t>(len) < N));
    return static_cast<std::streamsize>(len);
}

template <std::size_t N>
std::streamsize print_pos(wchar_t (&s)[N], std::size_t pos)
{
    const auto len = (pos != text_error::npos) ?
        std::swprintf(s, N, L"%zu", pos + 1) :
        std::swprintf(s, N, L"n/a");
    assert((len > 0 ) && (static_cast<std::size_t>(len) < N));
    return static_cast<std::streamsize>(len);
}

} // end namespace detail

template <class Tr>
std::basic_ostream<char, Tr>& operator<<(
    std::basic_ostream<char, Tr>& os, const text_error_info& i)
{
    if (const auto p = i.error().get_physical_position()) {
        // line
        char l[std::numeric_limits<std::size_t>::digits10 + 2];
        const auto l_len = detail::print_pos(l, p->first);

        // column
        char c[sizeof(l)];
        const auto c_len = detail::print_pos(c, p->second);

        // what
        const auto w = i.error().what();
        const auto w_len = static_cast<std::streamsize>(std::strlen(w));

        const auto n = w_len + l_len + c_len + ((w_len > 0) ? 15 : 27);

        return detail::formatted_output(os, n,
            [w, w_len, l = &l[0], l_len, c = &c[0], c_len]
            (auto* sb) {
                if (w_len > 0) {
                    if ((sb->sputn(w, w_len) != w_len)
                     || (sb->sputn("; line ", 7) != 7)) {
                        return false;
                    }
                } else if (sb->sputn("Text error at line ", 19) != 19) {
                    return false;
                }
                return (sb->sputn(l, l_len) == l_len)
                    && (sb->sputn(" column ", 8) == 8)
                    && (sb->sputn(c, c_len) == c_len);
            });

    } else {
        return os << i.error().what();
    }
}

template <class Tr>
std::basic_ostream<wchar_t, Tr>& operator<<(
    std::basic_ostream<wchar_t, Tr>& os, const text_error_info& i)
{
    // Count the wide characters in what, which may be an NTMBS
    auto w_raw = i.error().what();
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif
    auto w_len = static_cast<std::streamsize>(std::mbstowcs(0, w_raw, 0));
#ifdef _MSC_VER
#pragma warning(pop)
#endif
    if (w_len == -1) {
        // Conversion failed
        w_raw = "";
        w_len = 0;
    }

    if (const auto p = i.error().get_physical_position()) {
        // line
        wchar_t l[std::numeric_limits<std::size_t>::digits10 + 2];
        const auto l_len = detail::print_pos(l, p->first);

        // column
        wchar_t c[sizeof(l)];
        const auto c_len = detail::print_pos(c, p->second);

        const auto n = w_len + l_len + c_len + ((w_len > 0) ? 15 : 27);

        return detail::formatted_output(os, n,
            [w_raw, w_len, l = &l[0], l_len, c = &c[0], c_len]
            (auto* sb) {
                if (w_len > 0) {
                    std::unique_ptr<wchar_t[]> w(
                        new wchar_t[w_len + 1]);                    // throw
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif
                    std::mbstowcs(w.get(), w_raw, w_len);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
                    w[w_len] = L'\0';   // maybe not required
                    if ((sb->sputn(w.get(), w_len) != w_len)
                     || (sb->sputn(L"; line ", 7) != 7)) {
                        return false;
                    }
                } else if (sb->sputn(L"Text error at line ", 19) != 19) {
                    return false;
                }
                return (sb->sputn(l, l_len) == l_len)
                    && (sb->sputn(L" column ", 8) == 8)
                    && (sb->sputn(c, c_len) == c_len);
            });

    } else if (w_len > 0) {
        return detail::formatted_output(os, w_len,
            [w_raw, &w_len]
            (auto* sb) {
                std::unique_ptr<wchar_t[]> w(
                    new wchar_t[w_len + 1]);                        // throw
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif
                std::mbstowcs(w.get(), w_raw, w_len);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
                w[w_len] = L'\0';   // maybe not required
                return sb->sputn(w.get(), w_len) == w_len;
            });

    } else {
        return os;
    }
}

inline std::string to_string(const text_error_info& i)
{
    std::ostringstream s;
    s << i;
    return s.str();
}

inline std::wstring to_wstring(const text_error_info& i)
{
    std::wostringstream s;
    s << i;
    return s.str();
}

}}

#endif
<|endoftext|>