<commit_before>#include "migrate/migrate.hpp"
#include <getopt.h>
#include "help.hpp"
#include "string.h"
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>

namespace migrate {

void usage(UNUSED const char *name) {
    Help_Pager *help = Help_Pager::instance();
    help->pagef("Usage:\n"
                "        rethinkdb migrate --in -f <file_1> [-f <file_2> ...] --out -f <file_1> [-f <file_2>] [--intermediate file]\n");
    help->pagef("\n"
                "Migrate from one version of RethinkDB to another\n"
                "\n"
                "Options:\n"
                "  -f, --file            Path to file or block device where database goes.\n"
                "      --in              Specify input files, -f (or --file) flags following\n"
                "                        this command will be used to extract data from.\n"
                "      --out             Specify output files, -f (or --file) flags following\n"
                "                        this command is where the new database will go.\n"
                "      --intermediate    File to store intermediate raw memcached commands"
                "                        in. It defaults to: %s.\n", TEMP_MIGRATION_FILE);
    help->pagef("      --force           Allow migrate to overwrite an existing database file.\n");
    help->pagef("\n"
                "Migration extracts data from the old database into a portable format of raw\n"
                "memcached commands and then reinserts the data into a new file version being\n"
                "migrated to.\n"
                "Migration can done from a set of files to themselves. Effectively migrating\n"
                "in place. This requires a --force flag.\n"
                "Note: if migration in place is interrupted it has the potential to leave the\n"
                "target files with missing data. Should this happen the intermediate file will\n"
                "be the only remaining copy of the data. Please consult support for help getting\n"
                "this data back in to a database.\n");
    exit(0);
}

void parse_cmd_args(int argc, char **argv, config_t *config) {
    // TODO disallow rogue options.

    //Grab the exec-name
    config->exec_name = argv[0];
    argc--;
    argv++;

    enum reading_list_t {
        in = 0,
        out,
        unset
    } reading_list;

    reading_list = unset;

    optind = 1;  // reinit getopt.
    if (argc >= 2) {
        if (!strncmp("help", argv[1], 4)) {
            usage(argv[0]);
        }
    }
    for (;;) {
        int do_help = 0;

        /* Which list a -f argument goes into */
        int switch_to_reading_in_files = 0;
        int switch_to_reading_out_files = 0;

        static const struct option long_options[] =
            {
                {"in", no_argument, &switch_to_reading_in_files, 1},
                {"out", no_argument, &switch_to_reading_out_files, 1},
                {"file", required_argument, 0, 'f'},
                {"intermediate", required_argument, 0, 'i'},
                {"force", no_argument, (int *) &(config->force), 1},
                {"help", no_argument, &do_help, 1},
                {0, 0, 0, 0}
            };

        int option_index = 0;
        int c = getopt_long(argc, argv, "f:i:", long_options, &option_index);

        if (do_help) {
            c = 'h';
        }
        if (switch_to_reading_in_files) {
            reading_list = in;
        }
        if (switch_to_reading_out_files) {
            reading_list = out;
        }

        // Detect the end of the options.
        if (c == -1)
            break;

        switch (c) {
        case 0:
            break;
        case 'f':
            if (reading_list == in)
                config->input_filenames.push_back(optarg);
            else if (reading_list == out)
                config->output_filenames.push_back(optarg);
            else
                fail_due_to_user_error("-f argument must follow either a --in or a --out flag\n");
            break;
        case 'i':
            config->intermediate_file = optarg;
            break;
        default:
            // getopt_long already printed an error message.
            usage(argv[0]);
        }
    }

    if (optind < argc) {
        fail_due_to_user_error("Unexpected extra argument: \"%s\"", argv[optind]);
    }

    // Sanity checks

    if (config->input_filenames.empty()) {
        fprintf(stderr, "At least one input file must be specified.\n");
        usage(argv[0]);
    }

    {
        std::vector<std::string> names = config->input_filenames;
        std::sort(names.begin(), names.end());
        if (std::unique(names.begin(), names.end()) != names.end()) {
            fail_due_to_user_error("Duplicate file names provided.");
        }
    }
}

} // namespace migrate

//convert spaces to command line safe '\ ' space escapes Truly sucks that I
//have to write this, but the documentation for boost just wasn't explaining
//things to me, if anyone knows how to use replace all, please rewrite this
std::string escape_spaces(std::string str) {
    for (std::string::iterator it = str.begin(); it != str.end(); it++) {
        if (*it == ' ') {
            it = str.insert(it, '\\') + 1;
        }
    }
    return str;
}

int run_migrate(int argc, char **argv) {

    migrate::config_t cfg;
    migrate::parse_cmd_args(argc, argv, &cfg);

    //BREAKPOINT;
    std::vector<std::string> command_line;
    command_line.push_back("rdb_migrate");
    command_line.push_back("-r");
    command_line.push_back(cfg.exec_name);

    for (std::vector<std::string>::iterator it = cfg.input_filenames.begin(); it != cfg.input_filenames.end(); it++) {
        command_line.push_back("-i");
        command_line.push_back(escape_spaces(*it));
    }
    for (std::vector<std::string>::iterator it = cfg.output_filenames.begin(); it != cfg.output_filenames.end(); it++) {
        command_line.push_back("-o");
        command_line.push_back(escape_spaces(*it));
    }

    command_line.push_back("-s");
    command_line.push_back(cfg.intermediate_file);

    if (cfg.force)
        command_line.push_back("-f");

    int res = system(boost::algorithm::join(command_line, " ").c_str());
    if (res != 0)
        fprintf(stderr, "Migration failed.\n");

    return res;
}
<commit_msg>Polish and clarify migrate help output. (affects #359)<commit_after>#include "migrate/migrate.hpp"
#include <getopt.h>
#include "help.hpp"
#include "string.h"
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>

namespace migrate {

void usage(UNUSED const char *name) {
    Help_Pager *help = Help_Pager::instance();
    help->pagef("Usage:\n"
                "        rethinkdb migrate --in -f <file_1> [-f <file_2> ...] --out -f <file_1> [-f <file_2>] [--intermediate file]\n");
    help->pagef("\n"
                "Migrate from one version of RethinkDB to another\n"
                "\n"
                "Options:\n"
                "      --in              Specify input files, -f (or --file) flags following\n"
                "                        this command will be used to extract data from.\n"
                "      --out             Specify output files, -f (or --file) flags following\n"
                "                        this command is where the new database will go.\n"
                "  -f, --file            Path to a file or block device that constitutes to\n"
                "                        either the input or output database.\n"
                "      --intermediate    File to store intermediate raw memcached commands\n"
                "                        in. It defaults to: %s.\n", TEMP_MIGRATION_FILE);
    help->pagef("      --force           Allow migrate to overwrite an existing database file.\n");
    help->pagef("\n"
                "Migration extracts data from the old database into a portable format of raw\n"
                "memcached commands and then reinserts the data into a new file version being\n"
                "migrated to.\n"
                "Migration can be done from a set of files to themselves. Effectively migrating\n"
                "in place. This requires a --force flag.\n"
                "Note: if migration in place is interrupted it has the potential to leave the\n"
                "target files with missing data. Should this happen the intermediate file will\n"
                "be the only remaining copy of the data. Please consult support for help getting\n"
                "this data back in to a database.\n");
    exit(0);
}

void parse_cmd_args(int argc, char **argv, config_t *config) {
    // TODO disallow rogue options.

    //Grab the exec-name
    config->exec_name = argv[0];
    argc--;
    argv++;

    enum reading_list_t {
        in = 0,
        out,
        unset
    } reading_list;

    reading_list = unset;

    optind = 1;  // reinit getopt.
    if (argc >= 2) {
        if (!strncmp("help", argv[1], 4)) {
            usage(argv[0]);
        }
    }
    for (;;) {
        int do_help = 0;

        /* Which list a -f argument goes into */
        int switch_to_reading_in_files = 0;
        int switch_to_reading_out_files = 0;

        static const struct option long_options[] =
            {
                {"in", no_argument, &switch_to_reading_in_files, 1},
                {"out", no_argument, &switch_to_reading_out_files, 1},
                {"file", required_argument, 0, 'f'},
                {"intermediate", required_argument, 0, 'i'},
                {"force", no_argument, (int *) &(config->force), 1},
                {"help", no_argument, &do_help, 1},
                {0, 0, 0, 0}
            };

        int option_index = 0;
        int c = getopt_long(argc, argv, "f:i:", long_options, &option_index);

        if (do_help) {
            c = 'h';
        }
        if (switch_to_reading_in_files) {
            reading_list = in;
        }
        if (switch_to_reading_out_files) {
            reading_list = out;
        }

        // Detect the end of the options.
        if (c == -1)
            break;

        switch (c) {
        case 0:
            break;
        case 'f':
            if (reading_list == in)
                config->input_filenames.push_back(optarg);
            else if (reading_list == out)
                config->output_filenames.push_back(optarg);
            else
                fail_due_to_user_error("-f argument must follow either a --in or a --out flag\n");
            break;
        case 'i':
            config->intermediate_file = optarg;
            break;
        default:
            // getopt_long already printed an error message.
            usage(argv[0]);
        }
    }

    if (optind < argc) {
        fail_due_to_user_error("Unexpected extra argument: \"%s\"", argv[optind]);
    }

    // Sanity checks

    if (config->input_filenames.empty()) {
        fprintf(stderr, "At least one input file must be specified.\n");
        usage(argv[0]);
    }

    {
        std::vector<std::string> names = config->input_filenames;
        std::sort(names.begin(), names.end());
        if (std::unique(names.begin(), names.end()) != names.end()) {
            fail_due_to_user_error("Duplicate file names provided.");
        }
    }
}

} // namespace migrate

//convert spaces to command line safe '\ ' space escapes Truly sucks that I
//have to write this, but the documentation for boost just wasn't explaining
//things to me, if anyone knows how to use replace all, please rewrite this
std::string escape_spaces(std::string str) {
    for (std::string::iterator it = str.begin(); it != str.end(); it++) {
        if (*it == ' ') {
            it = str.insert(it, '\\') + 1;
        }
    }
    return str;
}

int run_migrate(int argc, char **argv) {

    migrate::config_t cfg;
    migrate::parse_cmd_args(argc, argv, &cfg);

    //BREAKPOINT;
    std::vector<std::string> command_line;
    command_line.push_back("rdb_migrate");
    command_line.push_back("-r");
    command_line.push_back(cfg.exec_name);

    for (std::vector<std::string>::iterator it = cfg.input_filenames.begin(); it != cfg.input_filenames.end(); it++) {
        command_line.push_back("-i");
        command_line.push_back(escape_spaces(*it));
    }
    for (std::vector<std::string>::iterator it = cfg.output_filenames.begin(); it != cfg.output_filenames.end(); it++) {
        command_line.push_back("-o");
        command_line.push_back(escape_spaces(*it));
    }

    command_line.push_back("-s");
    command_line.push_back(cfg.intermediate_file);

    if (cfg.force)
        command_line.push_back("-f");

    int res = system(boost::algorithm::join(command_line, " ").c_str());
    if (res != 0)
        fprintf(stderr, "Migration failed.\n");

    return res;
}
<|endoftext|>


<commit_before>#ifndef DUNE_DETAILED_DISCRETIZATIONS_LA_CONTAINER_FACTORY_EIGEN_HH
#define DUNE_DETAILED_DISCRETIZATIONS_LA_CONTAINER_FACTORY_EIGEN_HH

//#ifdef HAVE_EIGEN

#include <dune/common/shared_ptr.hh>

#include <dune/stuff/la/container/pattern.hh>
#include <dune/stuff/la/container/eigen.hh>

namespace Dune {
namespace Detailed {
namespace Discretizations {
namespace LA {
namespace Container {
namespace Factory {

template< class ElementType >
class Eigen
{
public:
  typedef Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >  RowMajorSparseMatrixType;
  typedef Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >           DenseMatrixType;
  typedef Dune::Stuff::LA::Container::EigenDenseVector< ElementType >           DenseVectorType;
  typedef Dune::Stuff::LA::Container::SparsityPatternDefault                    PatternType;

  template< class TestSpaceType, class AnsatzSpaceType >
  static Dune::shared_ptr< RowMajorSparseMatrixType > createRowMajorSparseMatrix(const TestSpaceType& testSpace,
                                                                                const AnsatzSpaceType& ansatzSpace)
  {
    typedef Dune::Stuff::LA::Container::SparsityPatternDefault PatternType;
    const Dune::shared_ptr< const PatternType > pattern = testSpace.computePattern(ansatzSpace);
    return createRowMajorSparseMatrix(testSpace, ansatzSpace, *pattern);
  } // static ... createRowMajorSparseMatrix(...)

  template< class TestSpaceType, class AnsatzSpaceType >
  static Dune::shared_ptr< RowMajorSparseMatrixType > createRowMajorSparseMatrix(const TestSpaceType& testSpace,
                                                                                const AnsatzSpaceType& ansatzSpace,
                                                                                const PatternType& pattern)
  {
    return Dune::make_shared< RowMajorSparseMatrixType >(testSpace.map().size(),
                                                         ansatzSpace.map().size(),
                                                         pattern);
  } // static ... createRowMajorSparseMatrix(...)

  template< class TestSpaceType, class AnsatzSpaceType >
  static Dune::shared_ptr< DenseMatrixType > createDenseMatrix(const TestSpaceType& testSpace,
                                                               const AnsatzSpaceType& ansatzSpace)
  {
    return Dune::make_shared< DenseMatrixType >(testSpace.map().size(),
                                                ansatzSpace.map().size());
  } // static ... createDenseMatrix(...)

  template< class SpaceType >
  static Dune::shared_ptr< DenseVectorType > createDenseVector(const SpaceType& space)
  {
    return Dune::make_shared< DenseVectorType >(space.map().size());
  } // static Dune::shared_ptr< DenseVectorType > createDenseVector(const SpaceType& space)
}; // class Eigen

} // namespace Factory
} // namespace Conatiner
} // namespace LA
} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

//#endif // HAVE_EIGEN

#endif // DUNE_DETAILED_DISCRETIZATIONS_LA_CONTAINER_FACTORY_EIGEN_HH
<commit_msg>[la.container.factory.eigen] reenabled HAVE_EIGEN guard<commit_after>#ifndef DUNE_DETAILED_DISCRETIZATIONS_LA_CONTAINER_FACTORY_EIGEN_HH
#define DUNE_DETAILED_DISCRETIZATIONS_LA_CONTAINER_FACTORY_EIGEN_HH

#ifdef HAVE_EIGEN

#include <dune/common/shared_ptr.hh>

#include <dune/stuff/la/container/pattern.hh>
#include <dune/stuff/la/container/eigen.hh>

namespace Dune {
namespace Detailed {
namespace Discretizations {
namespace LA {
namespace Container {
namespace Factory {

template< class ElementType >
class Eigen
{
public:
  typedef Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >  RowMajorSparseMatrixType;
  typedef Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >           DenseMatrixType;
  typedef Dune::Stuff::LA::Container::EigenDenseVector< ElementType >           DenseVectorType;
  typedef Dune::Stuff::LA::Container::SparsityPatternDefault                    PatternType;

  template< class TestSpaceType, class AnsatzSpaceType >
  static Dune::shared_ptr< RowMajorSparseMatrixType > createRowMajorSparseMatrix(const TestSpaceType& testSpace,
                                                                                const AnsatzSpaceType& ansatzSpace)
  {
    typedef Dune::Stuff::LA::Container::SparsityPatternDefault PatternType;
    const Dune::shared_ptr< const PatternType > pattern = testSpace.computePattern(ansatzSpace);
    return createRowMajorSparseMatrix(testSpace, ansatzSpace, *pattern);
  } // static ... createRowMajorSparseMatrix(...)

  template< class TestSpaceType, class AnsatzSpaceType >
  static Dune::shared_ptr< RowMajorSparseMatrixType > createRowMajorSparseMatrix(const TestSpaceType& testSpace,
                                                                                const AnsatzSpaceType& ansatzSpace,
                                                                                const PatternType& pattern)
  {
    return Dune::make_shared< RowMajorSparseMatrixType >(testSpace.map().size(),
                                                         ansatzSpace.map().size(),
                                                         pattern);
  } // static ... createRowMajorSparseMatrix(...)

  template< class TestSpaceType, class AnsatzSpaceType >
  static Dune::shared_ptr< DenseMatrixType > createDenseMatrix(const TestSpaceType& testSpace,
                                                               const AnsatzSpaceType& ansatzSpace)
  {
    return Dune::make_shared< DenseMatrixType >(testSpace.map().size(),
                                                ansatzSpace.map().size());
  } // static ... createDenseMatrix(...)

  template< class SpaceType >
  static Dune::shared_ptr< DenseVectorType > createDenseVector(const SpaceType& space)
  {
    return Dune::make_shared< DenseVectorType >(space.map().size());
  } // static Dune::shared_ptr< DenseVectorType > createDenseVector(const SpaceType& space)
}; // class Eigen

} // namespace Factory
} // namespace Conatiner
} // namespace LA
} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // HAVE_EIGEN

#endif // DUNE_DETAILED_DISCRETIZATIONS_LA_CONTAINER_FACTORY_EIGEN_HH
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "stdafx.h"

#include <limits>
#include <string>
#include <stdlib.h>

#include "common/common.h"
#include "util/ascii_util.h"

#include "decimal.h"
#include "floatimpl.h"
#include "integer.h"

#include "zorbaserialization/serialize_zorba_types.h"
#include "zorbaserialization/serialize_template_types.h"

///////////////////////////////////////////////////////////////////////////////

namespace zorba {

zstring const& nan_str() {
  static zstring const value( "NaN" );
  return value;
}

zstring const& pos_inf_str() {
  static zstring const value( "INF" );
  return value;
}

zstring const& neg_inf_str() {
  static zstring const value( "-INF" );
  return value;
}

////////////////////////////////////////////////////////////////////////////////

static void count_significant_digits( char digit, int *significant_digits,
                                      int *trailing_zeros ) {
  if ( digit == '0' )
    ++*trailing_zeros;
  else {
    if ( (*significant_digits)++ )
      *significant_digits += *trailing_zeros;
    *trailing_zeros = 0;
  }
}

template<typename F>
void FloatImpl<F>::parse( char const *s ) {
  if ( !*s )
    throw std::invalid_argument( "empty string" );

  int significant_digits = 0;

  s = ascii::trim_start_space( s );

  if ( !parse_etc( s ) ) {
    char const *const first_non_ws = s;
    int trailing_zeros = 0;
    //
    // We need got_digit to know that we're potentially parsing a floating
    // point value comprised of at least one digit -- which means the value
    // can't be one of the special values of INF, -INF, or NaN.
    //
    // We need to know this to prevent aton() from parsing the special values
    // since it (via strtod() that it uses) allows them regardless of case
    // whereas XQuery insists on a specific case.
    //
    bool got_digit = false;

    if ( *s == '+' || *s == '-' )
      ++s;
    if ( ascii::is_digit( *s ) ) {
      got_digit = true;
      do {
        count_significant_digits( *s, &significant_digits, &trailing_zeros );
      } while ( ascii::is_digit( *++s ) );
    }
    if ( *s == '.' && ascii::is_digit( *++s ) ) {
      got_digit = true;
      do {
        count_significant_digits( *s, &significant_digits, &trailing_zeros );
      } while ( ascii::is_digit( *++s ) );
    }
    if ( *s == 'e' || *s == 'E' ) {
      ++s;
      if ( *s == '+' || *s == '-' )
        ++s;
      if ( ascii::is_digit( *s ) ) {
        got_digit = true;
        while ( ascii::is_digit( *++s ) ) ;
      }
    }
    if ( !got_digit )
      throw std::invalid_argument(
        BUILD_STRING( '"', first_non_ws, "\": invalid floating-point literal" )
      );
    value_ = ztd::aton<value_type>( first_non_ws );
  }

  precision_ = significant_digits < max_precision() ?
    significant_digits : max_precision();
}

template<typename FloatType>
bool FloatImpl<FloatType>::parse_etc( char const *s ) {
  if ( strncmp( s, "INF", 3 ) == 0 ) {
    value_ = FloatImpl<FloatType>::pos_inf().value_;
    s += 3;
  } else if ( strncmp( s, "-INF", 4 ) == 0 ) {
    value_ = FloatImpl<FloatType>::neg_inf().value_;
    s += 4;
  } else if ( strncmp( s, "NaN", 3 ) == 0 ) {
    value_ = FloatImpl<FloatType>::nan().value_;
    s += 3;
  } else if ( strncmp( s, "+INF", 4 ) == 0 ) {
    value_ = FloatImpl<FloatType>::pos_inf().value_;
    s += 4;
  } else
    return false;

  return !*ascii::trim_start_space( s );
}

////////// constructors ///////////////////////////////////////////////////////

template<typename F>
FloatImpl<F>::FloatImpl( Decimal const &d ) {
  zstring const temp( d.toString() );
  parse( temp.c_str() );
}

template<typename F>
template<class T>
FloatImpl<F>::FloatImpl( IntegerImpl<T> const &i ) {
  zstring const temp( i.toString() );
  parse( temp.c_str() );
}

template FloatImpl<float>::FloatImpl( Integer const& );
template FloatImpl<float>::FloatImpl( NegativeInteger const& );
template FloatImpl<float>::FloatImpl( NonNegativeInteger const& );
template FloatImpl<float>::FloatImpl( NonPositiveInteger const& );
template FloatImpl<float>::FloatImpl( PositiveInteger const& );

template FloatImpl<double>::FloatImpl( Integer const& );
template FloatImpl<double>::FloatImpl( NegativeInteger const& );
template FloatImpl<double>::FloatImpl( NonNegativeInteger const& );
template FloatImpl<double>::FloatImpl( NonPositiveInteger const& );
template FloatImpl<double>::FloatImpl( PositiveInteger const& );

////////// assignment operators ///////////////////////////////////////////////

template<typename F>
FloatImpl<F>& FloatImpl<F>::operator=( Decimal const &d ) {
  zstring const temp( d.toString() );
  parse( temp.c_str() );
  return *this;
}

template<typename F>
template<class T>
FloatImpl<F>& FloatImpl<F>::operator=( IntegerImpl<T> const &i ) {
  zstring const temp( i.toString() );
  parse( temp.c_str() );
  return *this;
}

#define ZORBA_INSTANTIATE(F,I) \
  template FloatImpl<F>& FloatImpl<F>::operator=( I const& )

ZORBA_INSTANTIATE(float,Integer);
ZORBA_INSTANTIATE(float,NegativeInteger);
ZORBA_INSTANTIATE(float,NonNegativeInteger);
ZORBA_INSTANTIATE(float,NonPositiveInteger);
ZORBA_INSTANTIATE(float,PositiveInteger);

ZORBA_INSTANTIATE(double,Integer);
ZORBA_INSTANTIATE(double,NegativeInteger);
ZORBA_INSTANTIATE(double,NonNegativeInteger);
ZORBA_INSTANTIATE(double,NonPositiveInteger);
ZORBA_INSTANTIATE(double,PositiveInteger);
#undef ZORBA_INSTANTIATE

////////// math functions /////////////////////////////////////////////////////

template<typename F>
FloatImpl<F> FloatImpl<F>::acos() const {
  if ( *this < numeric_consts<FloatImpl>::neg_one() ||
       *this > numeric_consts<FloatImpl>::one() )
    return nan();
  return FloatImpl<F>(
    isNegZero() ? -std::acos( value_ ) : std::acos( value_ )
  );
}

template<typename F>
FloatImpl<F> FloatImpl<F>::asin() const {
  if ( *this < numeric_consts<FloatImpl>::neg_one() ||
       *this > numeric_consts<FloatImpl>::one() )
    return nan();
  return FloatImpl<F>( std::asin( value_ ) );
}

template<typename F>
void FloatImpl<F>::frexp( FloatImpl<F> &out_mantissa,
                          Integer &out_exponent ) const {
  int expint;
  out_mantissa = FloatImpl( ::frexp( value_, &expint ) );
  out_exponent = Integer( expint );
}

template<>
void FloatImpl<double>::modf( FloatImpl<double> &out_fraction,
                              FloatImpl<double> &out_integer ) const {
  double int_part;
  out_fraction = std::modf( value_, &int_part );
  out_integer = int_part;
}

template<>
void FloatImpl<float>::modf( FloatImpl<float> &out_fraction,
                             FloatImpl<float> &out_integer ) const {
  float int_part;
  out_fraction = ::modff( value_, &int_part );
  out_integer = int_part;
}

template<typename F>
FloatImpl<F> FloatImpl<F>::round() const {
  return round( numeric_consts<xs_integer>::zero() );
}

template<typename F>
FloatImpl<F> FloatImpl<F>::round( Integer const &precision ) const {
  FloatImpl result;
  if ( isFinite() && !isZero() ) {
    MAPM m(
      Decimal::round2(
        Decimal::value_type( value_ ),
        Decimal::value_type( precision.itod() )
      )
    );
    if ( value_ < 0 && m.sign() == 0 )
      result = neg_zero();
    else {
      char buf[200];
      m.toString( buf, ZORBA_FLOAT_POINT_PRECISION );
      result.parse( buf );
    }
  } else
    result.value_ = value_;

  return result;
}

template<typename F>
FloatImpl<F> FloatImpl<F>::roundHalfToEven( Integer const &precision ) const {
  FloatImpl result;
  if ( isFinite() && !isZero() ) {
    MAPM m(
      Decimal::roundHalfToEven2(
        Decimal::value_type( value_ ),
        Decimal::value_type( precision.itod() )
      )
    );
    if ( value_ < 0 && m.sign() == 0 )
      result = neg_zero();
    else {
      char buf[200];
      m.toString( buf, ZORBA_FLOAT_POINT_PRECISION );
      result.parse( buf );
    }
  } else
    result.value_ = value_;
  return result;
}

////////// miscellaneous //////////////////////////////////////////////////////

template<>
bool FloatImpl<double>::isNegZero() const {
  if ( !value_ ) {
    char const *const bytes = reinterpret_cast<char const*>( &value_ );
    // test for little endian and big endian
    return bytes[0] || bytes[7];        // TODO: depends on sizeof(double)
  }
  return false;
}

template<>
bool FloatImpl<float>::isNegZero() const {
  if ( !value_ ) {
    char const *const bytes = reinterpret_cast<char const*>( &value_ );
    // test for little endian and big endian
    return bytes[0] || bytes[3];        // TODO: depends on sizeof(float)
  }
  return false;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::nan() {
  static FloatImpl<F> const value( std::sqrt( -1.0 ) );
  return value;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::neg_inf() {
  static FloatImpl<F> const value( -std::numeric_limits<F>::infinity() );
  return value;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::neg_zero() {
  static FloatImpl<F> const value( -0.0 );
  return value;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::pos_inf() {
  static FloatImpl<F> const value( std::numeric_limits<F>::infinity() );
  return value;
}

template<typename F>
zstring FloatImpl<F>::toIntegerString() const {
  if ( isNaN() )
    return nan_str();
  if  (isPosInf() )
    return pos_inf_str();
  if ( isNegInf() )
    return neg_inf_str();
  if ( isPosZero() )
    return "0";
  if ( isNegZero() )
    return "-0";
  return ztd::to_string( static_cast<long long>( value_ ) );
}

template<typename F>
zstring FloatImpl<F>::toString( bool no_scientific_format ) const {
  if ( isNaN() )
    return nan_str();
  if ( isPosInf() )
    return pos_inf_str();
  if ( isNegInf() )
    return neg_inf_str();
  if ( isPosZero() )
    return "0";
  if ( isNegZero() )
    return "-0";

  value_type const abs_val = fabs( value_ );
  value_type const lower = 0.000001f, upper = 1000000.0f;

  if ( no_scientific_format || (abs_val >= lower && abs_val < upper) ||
       abs_val == 0 ) {
#if 1
    // This is the "spec" implementation, i.e., it is an exact application of
    // the spec in  http://www.w3.org/TR/xpath-functions/#casting
    MAPM temp( value_ );
    temp = temp.round( precision_ );
    return Decimal::toString( temp, isNegZero(), precision_ );
#else
    std::stringstream stream;
    stream.precision(7);
    stream.setf(std::ios::fixed);
    stream << value_;

    zstring result(stream.str());

    // remove non-significant trailing 0's
    long i = result.size() - 1;
    while (str[i] == '0')
      --i;

    if (i >= 0) {
      long j = i;
      while (str[j] != '.')
        --j;

      if (j >= 0)
        if (j == i)
          result.resize(i);
        else
          result.resize(i+1);
    }

    return result;
#endif
  } else {
    char format[15];
    sprintf( format, "%%#1.%dE", static_cast<int>( precision_ ) );

    char buf[174];
    sprintf( buf, format, static_cast<double>( value_ ) );

    char *e = strchr( buf, 'E' );
    char *zeros = e ? e - 1 : buf + strlen( buf ) - 1;

    while ( *zeros == '0' )
      --zeros;

    if ( e ) {
      if ( *zeros == '.' )
        ++zeros;

      zeros[1] = 'E';
      ++e;

      if ( *e == '+' )
        ++e;
      else if ( *e == '-' ) {
        ++zeros;
        zeros[1] = '-';
        ++e;
      }

      while ( *e == '0' )
        ++e;

      memmove( (void*)(zeros + 2), e, strlen( e ) + 1 );
    } else {
      if ( *zeros == '.' )
        --zeros;
      zeros[1] = '\0';
    }

    Decimal::reduce( buf );
    return buf;
  }
}

///////////////////////////////////////////////////////////////////////////////

template class FloatImpl<double>;
template class FloatImpl<float>;

#ifdef WIN32
// exported for testing only
template class ZORBA_DLL_PUBLIC FloatImpl<double>;
template class ZORBA_DLL_PUBLIC FloatImpl<float>;
#endif /* WIN32 */

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>Put original precision back.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "stdafx.h"

#include <limits>
#include <string>
#include <stdlib.h>

#include "common/common.h"
#include "util/ascii_util.h"

#include "decimal.h"
#include "floatimpl.h"
#include "integer.h"

#include "zorbaserialization/serialize_zorba_types.h"
#include "zorbaserialization/serialize_template_types.h"

///////////////////////////////////////////////////////////////////////////////

namespace zorba {

zstring const& nan_str() {
  static zstring const value( "NaN" );
  return value;
}

zstring const& pos_inf_str() {
  static zstring const value( "INF" );
  return value;
}

zstring const& neg_inf_str() {
  static zstring const value( "-INF" );
  return value;
}

////////////////////////////////////////////////////////////////////////////////

static void count_significant_digits( char digit, int *significant_digits,
                                      int *trailing_zeros ) {
  if ( digit == '0' )
    ++*trailing_zeros;
  else {
    if ( (*significant_digits)++ )
      *significant_digits += *trailing_zeros;
    *trailing_zeros = 0;
  }
}

template<typename F>
void FloatImpl<F>::parse( char const *s ) {
  if ( !*s )
    throw std::invalid_argument( "empty string" );

  int significant_digits = 0;

  s = ascii::trim_start_space( s );

  if ( !parse_etc( s ) ) {
    char const *const first_non_ws = s;
    int trailing_zeros = 0;
    //
    // We need got_digit to know that we're potentially parsing a floating
    // point value comprised of at least one digit -- which means the value
    // can't be one of the special values of INF, -INF, or NaN.
    //
    // We need to know this to prevent aton() from parsing the special values
    // since it (via strtod() that it uses) allows them regardless of case
    // whereas XQuery insists on a specific case.
    //
    bool got_digit = false;

    if ( *s == '+' || *s == '-' )
      ++s;
    if ( ascii::is_digit( *s ) ) {
      got_digit = true;
      do {
        count_significant_digits( *s, &significant_digits, &trailing_zeros );
      } while ( ascii::is_digit( *++s ) );
    }
    if ( *s == '.' && ascii::is_digit( *++s ) ) {
      got_digit = true;
      do {
        count_significant_digits( *s, &significant_digits, &trailing_zeros );
      } while ( ascii::is_digit( *++s ) );
    }
    if ( *s == 'e' || *s == 'E' ) {
      ++s;
      if ( *s == '+' || *s == '-' )
        ++s;
      if ( ascii::is_digit( *s ) ) {
        got_digit = true;
        while ( ascii::is_digit( *++s ) ) ;
      }
    }
    if ( !got_digit )
      throw std::invalid_argument(
        BUILD_STRING( '"', first_non_ws, "\": invalid floating-point literal" )
      );
    value_ = ztd::aton<value_type>( first_non_ws );
  }

  precision_ = significant_digits < max_precision() ?
    significant_digits : max_precision();
}

template<typename FloatType>
bool FloatImpl<FloatType>::parse_etc( char const *s ) {
  if ( strncmp( s, "INF", 3 ) == 0 ) {
    value_ = FloatImpl<FloatType>::pos_inf().value_;
    s += 3;
  } else if ( strncmp( s, "-INF", 4 ) == 0 ) {
    value_ = FloatImpl<FloatType>::neg_inf().value_;
    s += 4;
  } else if ( strncmp( s, "NaN", 3 ) == 0 ) {
    value_ = FloatImpl<FloatType>::nan().value_;
    s += 3;
  } else if ( strncmp( s, "+INF", 4 ) == 0 ) {
    value_ = FloatImpl<FloatType>::pos_inf().value_;
    s += 4;
  } else
    return false;

  return !*ascii::trim_start_space( s );
}

////////// constructors ///////////////////////////////////////////////////////

template<typename F>
FloatImpl<F>::FloatImpl( Decimal const &d ) {
  zstring const temp( d.toString() );
  parse( temp.c_str() );
}

template<typename F>
template<class T>
FloatImpl<F>::FloatImpl( IntegerImpl<T> const &i ) {
  zstring const temp( i.toString() );
  parse( temp.c_str() );
}

template FloatImpl<float>::FloatImpl( Integer const& );
template FloatImpl<float>::FloatImpl( NegativeInteger const& );
template FloatImpl<float>::FloatImpl( NonNegativeInteger const& );
template FloatImpl<float>::FloatImpl( NonPositiveInteger const& );
template FloatImpl<float>::FloatImpl( PositiveInteger const& );

template FloatImpl<double>::FloatImpl( Integer const& );
template FloatImpl<double>::FloatImpl( NegativeInteger const& );
template FloatImpl<double>::FloatImpl( NonNegativeInteger const& );
template FloatImpl<double>::FloatImpl( NonPositiveInteger const& );
template FloatImpl<double>::FloatImpl( PositiveInteger const& );

////////// assignment operators ///////////////////////////////////////////////

template<typename F>
FloatImpl<F>& FloatImpl<F>::operator=( Decimal const &d ) {
  zstring const temp( d.toString() );
  parse( temp.c_str() );
  return *this;
}

template<typename F>
template<class T>
FloatImpl<F>& FloatImpl<F>::operator=( IntegerImpl<T> const &i ) {
  zstring const temp( i.toString() );
  parse( temp.c_str() );
  return *this;
}

#define ZORBA_INSTANTIATE(F,I) \
  template FloatImpl<F>& FloatImpl<F>::operator=( I const& )

ZORBA_INSTANTIATE(float,Integer);
ZORBA_INSTANTIATE(float,NegativeInteger);
ZORBA_INSTANTIATE(float,NonNegativeInteger);
ZORBA_INSTANTIATE(float,NonPositiveInteger);
ZORBA_INSTANTIATE(float,PositiveInteger);

ZORBA_INSTANTIATE(double,Integer);
ZORBA_INSTANTIATE(double,NegativeInteger);
ZORBA_INSTANTIATE(double,NonNegativeInteger);
ZORBA_INSTANTIATE(double,NonPositiveInteger);
ZORBA_INSTANTIATE(double,PositiveInteger);
#undef ZORBA_INSTANTIATE

////////// math functions /////////////////////////////////////////////////////

template<typename F>
FloatImpl<F> FloatImpl<F>::acos() const {
  if ( *this < numeric_consts<FloatImpl>::neg_one() ||
       *this > numeric_consts<FloatImpl>::one() )
    return nan();
  return FloatImpl<F>(
    isNegZero() ? -std::acos( value_ ) : std::acos( value_ )
  );
}

template<typename F>
FloatImpl<F> FloatImpl<F>::asin() const {
  if ( *this < numeric_consts<FloatImpl>::neg_one() ||
       *this > numeric_consts<FloatImpl>::one() )
    return nan();
  return FloatImpl<F>( std::asin( value_ ) );
}

template<typename F>
void FloatImpl<F>::frexp( FloatImpl<F> &out_mantissa,
                          Integer &out_exponent ) const {
  int expint;
  out_mantissa = FloatImpl( ::frexp( value_, &expint ) );
  out_exponent = Integer( expint );
}

template<>
void FloatImpl<double>::modf( FloatImpl<double> &out_fraction,
                              FloatImpl<double> &out_integer ) const {
  double int_part;
  out_fraction = std::modf( value_, &int_part );
  out_integer = int_part;
}

template<>
void FloatImpl<float>::modf( FloatImpl<float> &out_fraction,
                             FloatImpl<float> &out_integer ) const {
  float int_part;
  out_fraction = ::modff( value_, &int_part );
  out_integer = int_part;
}

template<typename F>
FloatImpl<F> FloatImpl<F>::round() const {
  return round( numeric_consts<xs_integer>::zero() );
}

template<typename F>
FloatImpl<F> FloatImpl<F>::round( Integer const &precision ) const {
  FloatImpl result;
  if ( isFinite() && !isZero() ) {
    MAPM m(
      Decimal::round2(
        Decimal::value_type( value_ ),
        Decimal::value_type( precision.itod() )
      )
    );
    if ( value_ < 0 && m.sign() == 0 )
      result = neg_zero();
    else {
      char buf[200];
      m.toString( buf, ZORBA_FLOAT_POINT_PRECISION );
      result.parse( buf );
    }
  } else
    result.value_ = value_;

  return result;
}

template<typename F>
FloatImpl<F> FloatImpl<F>::roundHalfToEven( Integer const &precision ) const {
  FloatImpl result;
  if ( isFinite() && !isZero() ) {
    MAPM m(
      Decimal::roundHalfToEven2(
        Decimal::value_type( value_ ),
        Decimal::value_type( precision.itod() )
      )
    );
    if ( value_ < 0 && m.sign() == 0 )
      result = neg_zero();
    else {
      char buf[200];
      m.toString( buf, ZORBA_FLOAT_POINT_PRECISION );
      result.parse( buf );
    }
  } else
    result.value_ = value_;
  return result;
}

////////// miscellaneous //////////////////////////////////////////////////////

template<>
bool FloatImpl<double>::isNegZero() const {
  if ( !value_ ) {
    char const *const bytes = reinterpret_cast<char const*>( &value_ );
    // test for little endian and big endian
    return bytes[0] || bytes[7];        // TODO: depends on sizeof(double)
  }
  return false;
}

template<>
bool FloatImpl<float>::isNegZero() const {
  if ( !value_ ) {
    char const *const bytes = reinterpret_cast<char const*>( &value_ );
    // test for little endian and big endian
    return bytes[0] || bytes[3];        // TODO: depends on sizeof(float)
  }
  return false;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::nan() {
  static FloatImpl<F> const value( std::sqrt( -1.0 ) );
  return value;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::neg_inf() {
  static FloatImpl<F> const value( -std::numeric_limits<F>::infinity() );
  return value;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::neg_zero() {
  static FloatImpl<F> const value( -0.0 );
  return value;
}

template<typename F>
FloatImpl<F> const& FloatImpl<F>::pos_inf() {
  static FloatImpl<F> const value( std::numeric_limits<F>::infinity() );
  return value;
}

template<typename F>
zstring FloatImpl<F>::toIntegerString() const {
  if ( isNaN() )
    return nan_str();
  if  (isPosInf() )
    return pos_inf_str();
  if ( isNegInf() )
    return neg_inf_str();
  if ( isPosZero() )
    return "0";
  if ( isNegZero() )
    return "-0";
  return ztd::to_string( static_cast<long long>( value_ ) );
}

template<typename F>
zstring FloatImpl<F>::toString( bool no_scientific_format ) const {
  if ( isNaN() )
    return nan_str();
  if ( isPosInf() )
    return pos_inf_str();
  if ( isNegInf() )
    return neg_inf_str();
  if ( isPosZero() )
    return "0";
  if ( isNegZero() )
    return "-0";

  value_type const abs_val = fabs( value_ );
  value_type const lower = 0.000001f, upper = 1000000.0f;

  if ( no_scientific_format || (abs_val >= lower && abs_val < upper) ||
       abs_val == 0 ) {
#if 1
    // This is the "spec" implementation, i.e., it is an exact application of
    // the spec in  http://www.w3.org/TR/xpath-functions/#casting
    MAPM temp( value_ );
    temp = temp.round( precision_ );
    return Decimal::toString( temp, isNegZero(), max_precision() );
#else
    std::stringstream stream;
    stream.precision(7);
    stream.setf(std::ios::fixed);
    stream << value_;

    zstring result(stream.str());

    // remove non-significant trailing 0's
    long i = result.size() - 1;
    while (str[i] == '0')
      --i;

    if (i >= 0) {
      long j = i;
      while (str[j] != '.')
        --j;

      if (j >= 0)
        if (j == i)
          result.resize(i);
        else
          result.resize(i+1);
    }

    return result;
#endif
  } else {
    char format[15];
    sprintf( format, "%%#1.%dE", static_cast<int>( precision_ ) );

    char buf[174];
    sprintf( buf, format, static_cast<double>( value_ ) );

    char *e = strchr( buf, 'E' );
    char *zeros = e ? e - 1 : buf + strlen( buf ) - 1;

    while ( *zeros == '0' )
      --zeros;

    if ( e ) {
      if ( *zeros == '.' )
        ++zeros;

      zeros[1] = 'E';
      ++e;

      if ( *e == '+' )
        ++e;
      else if ( *e == '-' ) {
        ++zeros;
        zeros[1] = '-';
        ++e;
      }

      while ( *e == '0' )
        ++e;

      memmove( (void*)(zeros + 2), e, strlen( e ) + 1 );
    } else {
      if ( *zeros == '.' )
        --zeros;
      zeros[1] = '\0';
    }

    Decimal::reduce( buf );
    return buf;
  }
}

///////////////////////////////////////////////////////////////////////////////

template class FloatImpl<double>;
template class FloatImpl<float>;

#ifdef WIN32
// exported for testing only
template class ZORBA_DLL_PUBLIC FloatImpl<double>;
template class ZORBA_DLL_PUBLIC FloatImpl<float>;
#endif /* WIN32 */

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before><commit_msg>debugged always true condition<commit_after><|endoftext|>


<commit_before>/***********************************************************************
 fields.cpp - Implements the Fields class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "fields.h"

#include "result.h"

namespace mysqlpp {

Fields::size_type Fields::size() const
{
	return res_->num_fields();
}

const Field&
Fields::at(int i) const
{
	res_->field_seek(i);
	return res_->fetch_field();
}

} // end namespace mysqlpp
<commit_msg>Comment change<commit_after>/***********************************************************************
 fields.cpp - Implements the Fields class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "fields.h"

#include "result.h"

namespace mysqlpp {

Fields::size_type Fields::size() const
{
	return res_->num_fields();
}

const Field&
Fields::at(int i) const
{
	res_->field_seek(i);
	return res_->fetch_field();
}

} // end namespace mysqlpp
<|endoftext|>


<commit_before>// Author: Stefan Wunsch, Enrico Guiraud CERN  09/2020

/*************************************************************************
 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RDF_RRESULTHANDLE
#define ROOT_RDF_RRESULTHANDLE

#include "ROOT/RResultPtr.hxx"
#include "ROOT/RDF/RLoopManager.hxx"
#include "ROOT/RDF/RActionBase.hxx"
#include "ROOT/RDF/Utils.hxx" // TypeID2TypeName

#include <memory>
#include <sstream>
#include <typeinfo>
#include <stdexcept> // std::runtime_error

namespace ROOT {
namespace RDF {

class RResultHandle {
   ROOT::Detail::RDF::RLoopManager* fLoopManager; //< Pointer to the loop manager
   /// Owning pointer to the action that will produce this result.
   /// Ownership is shared with RResultPtrs and RResultHandles that refer to the same result.
   std::shared_ptr<ROOT::Internal::RDF::RActionBase> fActionPtr;
   std::shared_ptr<void> fObjPtr; ///< Type erased shared pointer encapsulating the wrapped result
   const std::type_info& fType; ///< Type of the wrapped result

   // The ROOT::RDF::RunGraphs helper has to access the loop manager to check whether two RResultHandles belong to the same computation graph
   friend void RunGraphs(std::vector<RResultHandle>);

   /// Get the pointer to the encapsulated result.
   /// Ownership is not transferred to the caller.
   /// Triggers event loop and execution of all actions booked in the associated RLoopManager.
   void* Get()
   {
      if (!fActionPtr->HasRun())
         fLoopManager->Run();
      return fObjPtr.get();
   }

   /// Compare given type to the type of the wrapped result and throw if the types don't match.
   void CheckType(const std::type_info& type)
   {
      if (fType != type) {
         std::stringstream ss;
         ss << "Got the type " << ROOT::Internal::RDF::TypeID2TypeName(type)
            << " but the RResultHandle refers to a result of type " << ROOT::Internal::RDF::TypeID2TypeName(fType)
            << ".";
         throw std::runtime_error(ss.str());
      }
   }

public:
   template <class T>
   RResultHandle(const RResultPtr<T> &resultPtr) : fLoopManager(resultPtr.fLoopManager), fActionPtr(resultPtr.fActionPtr), fObjPtr(resultPtr.fObjPtr), fType(typeid(T)) {}

   RResultHandle(const RResultHandle&) = default;
   RResultHandle(RResultHandle&&) = default;

   /// Get the pointer to the encapsulated object.
   /// Triggers event loop and execution of all actions booked in the associated RLoopManager.
   /// \tparam T Type of the action result
   template <class T>
   T* GetPtr()
   {
      CheckType(typeid(T));
      return static_cast<T*>(Get());
   }

   /// Get a const reference to the encapsulated object.
   /// Triggers event loop and execution of all actions booked in the associated RLoopManager.
   /// \tparam T Type of the action result
   template <class T>
   const T& GetValue()
   {
      CheckType(typeid(T));
      return *static_cast<T*>(Get());
   }

   /// Check whether the result has already been computed
   ///
   /// ~~~{.cpp}
   /// std::vector<RResultHandle> results;
   /// results.emplace_back(df.Mean<double>("var"));
   /// res.IsReady(); // false, access will trigger event loop
   /// std::cout << res.GetValue<double>() << std::endl; // triggers event loop
   /// res.IsReady(); // true
   /// ~~~
   bool IsReady() const {
      return fActionPtr->HasRun();
   }

   bool operator==(const RResultHandle &rhs) const
   {
      return fObjPtr == rhs.fObjPtr;
   }

   bool operator!=(const RResultHandle &rhs) const
   {
      return !(fObjPtr == rhs.fObjPtr);
   }
};

} // namespace RDF
} // namespace ROOT

#endif // ROOT_RDF_RRESULTHANDLE
<commit_msg>[DF] Make RResultHandle default-constructible<commit_after>// Author: Stefan Wunsch, Enrico Guiraud CERN  09/2020

/*************************************************************************
 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RDF_RRESULTHANDLE
#define ROOT_RDF_RRESULTHANDLE

#include "ROOT/RResultPtr.hxx"
#include "ROOT/RDF/RLoopManager.hxx"
#include "ROOT/RDF/RActionBase.hxx"
#include "ROOT/RDF/Utils.hxx" // TypeID2TypeName

#include <memory>
#include <sstream>
#include <typeinfo>
#include <stdexcept> // std::runtime_error

namespace ROOT {
namespace RDF {

class RResultHandle {
   ROOT::Detail::RDF::RLoopManager *fLoopManager = nullptr; //< Pointer to the loop manager
   /// Owning pointer to the action that will produce this result.
   /// Ownership is shared with RResultPtrs and RResultHandles that refer to the same result.
   std::shared_ptr<ROOT::Internal::RDF::RActionBase> fActionPtr;
   std::shared_ptr<void> fObjPtr; ///< Type erased shared pointer encapsulating the wrapped result
   const std::type_info *fType = nullptr; ///< Type of the wrapped result

   // The ROOT::RDF::RunGraphs helper has to access the loop manager to check whether two RResultHandles belong to the same computation graph
   friend void RunGraphs(std::vector<RResultHandle>);

   /// Get the pointer to the encapsulated result.
   /// Ownership is not transferred to the caller.
   /// Triggers event loop and execution of all actions booked in the associated RLoopManager.
   void* Get()
   {
      if (!fActionPtr->HasRun())
         fLoopManager->Run();
      return fObjPtr.get();
   }

   /// Compare given type to the type of the wrapped result and throw if the types don't match.
   void CheckType(const std::type_info& type)
   {
      if (*fType != type) {
         std::stringstream ss;
         ss << "Got the type " << ROOT::Internal::RDF::TypeID2TypeName(type)
            << " but the RResultHandle refers to a result of type " << ROOT::Internal::RDF::TypeID2TypeName(*fType)
            << ".";
         throw std::runtime_error(ss.str());
      }
   }

   void ThrowIfNull()
   {
      if (fObjPtr == nullptr)
         throw std::runtime_error("Trying to access the contents of a null RResultHandle.");
   }

public:
   template <class T>
   RResultHandle(const RResultPtr<T> &resultPtr) : fLoopManager(resultPtr.fLoopManager), fActionPtr(resultPtr.fActionPtr), fObjPtr(resultPtr.fObjPtr), fType(&typeid(T)) {}

   RResultHandle(const RResultHandle&) = default;
   RResultHandle(RResultHandle&&) = default;
   RResultHandle() = default;

   /// Get the pointer to the encapsulated object.
   /// Triggers event loop and execution of all actions booked in the associated RLoopManager.
   /// \tparam T Type of the action result
   template <class T>
   T* GetPtr()
   {
      ThrowIfNull();
      CheckType(typeid(T));
      return static_cast<T*>(Get());
   }

   /// Get a const reference to the encapsulated object.
   /// Triggers event loop and execution of all actions booked in the associated RLoopManager.
   /// \tparam T Type of the action result
   template <class T>
   const T& GetValue()
   {
      ThrowIfNull();
      CheckType(typeid(T));
      return *static_cast<T*>(Get());
   }

   /// Check whether the result has already been computed
   ///
   /// ~~~{.cpp}
   /// std::vector<RResultHandle> results;
   /// results.emplace_back(df.Mean<double>("var"));
   /// res.IsReady(); // false, access will trigger event loop
   /// std::cout << res.GetValue<double>() << std::endl; // triggers event loop
   /// res.IsReady(); // true
   /// ~~~
   bool IsReady() const {
      if (fActionPtr == nullptr)
         return false;
      return fActionPtr->HasRun();
   }

   bool operator==(const RResultHandle &rhs) const
   {
      return fObjPtr == rhs.fObjPtr;
   }

   bool operator!=(const RResultHandle &rhs) const
   {
      return !(fObjPtr == rhs.fObjPtr);
   }
};

} // namespace RDF
} // namespace ROOT

#endif // ROOT_RDF_RRESULTHANDLE
<|endoftext|>


<commit_before>#include "ProfileHandler.h"

#include "SwitchHandler.h"

ProfileHandler::~ProfileHandler() {
  Serial.println("Freeing resources");

  for(int i = 0 ; i < this->inTopicsCount ; i++ ) {
    this->client->unsubscribe(this->inTopics[i]);
    free(this->inTopics[i]);
  }
  free(this->inTopics);
};

void ProfileHandler::setMqttClient(MQTTClient* client) {
  this->client = client;
};

void ProfileHandler::setup(JsonObject& config) {
  JsonArray& inTopics = config["in_topics"];

  this->inTopicsCount = inTopics.size();
  this->inTopics = (char**) malloc (this->inTopicsCount * sizeof( char* ));

  for(int i = 0 ; i < this->inTopicsCount ; i++) {
    this->inTopics[i] = strdup(inTopics[i].asString());
  }

  this->outTopic = strdup( config["out_topic"].asString());
};

void ProfileHandler::init() {
  for(int i = 0 ; i < this->inTopicsCount ; i++ ) {
    Serial.print("Subscribe to ");
    Serial.println(this->inTopics[i]);
    this->client->subscribe(this->inTopics[i]);
  }
};

/* Factory method for ProfileHandler's */
ProfileHandler*  ProfileHandler::createHandler(short int type) {
  switch(type) {
    case YAHA_TYPE_SWITCH:
      return new SwitchHandler();
  }
  return NULL;
};

bool ProfileHandler::handle(char topic[], char payload[], int length) {
  for(int i = 0 ; i < this->inTopicsCount ; i++ ) {
    if (strcmp(this->inTopics[i], topic) == 0) { //I'm listening this topic, so I need to get to work
      this->doHandle(topic, payload, length);
      return true;
    }
  }
  return false;
};

<commit_msg>Print unhandled types<commit_after>#include "ProfileHandler.h"

#include "SwitchHandler.h"

ProfileHandler::~ProfileHandler() {
  Serial.println("Freeing resources");

  for(int i = 0 ; i < this->inTopicsCount ; i++ ) {
    this->client->unsubscribe(this->inTopics[i]);
    free(this->inTopics[i]);
  }
  free(this->inTopics);
};

void ProfileHandler::setMqttClient(MQTTClient* client) {
  this->client = client;
};

void ProfileHandler::setup(JsonObject& config) {
  JsonArray& inTopics = config["in_topics"];

  this->inTopicsCount = inTopics.size();
  this->inTopics = (char**) malloc (this->inTopicsCount * sizeof( char* ));

  for(int i = 0 ; i < this->inTopicsCount ; i++) {
    this->inTopics[i] = strdup(inTopics[i].asString());
  }

  this->outTopic = strdup( config["out_topic"].asString());
};

void ProfileHandler::init() {
  for(int i = 0 ; i < this->inTopicsCount ; i++ ) {
    Serial.print("Subscribe to ");
    Serial.println(this->inTopics[i]);
    this->client->subscribe(this->inTopics[i]);
  }
};

/* Factory method for ProfileHandler's */
ProfileHandler*  ProfileHandler::createHandler(short int type) {
  switch(type) {
    case YAHA_TYPE_SWITCH:
      return new SwitchHandler();
  }
  Serial.print("Unknown handler type: ");
  Serial.println(type);
  return NULL;
};

bool ProfileHandler::handle(char topic[], char payload[], int length) {
  for(int i = 0 ; i < this->inTopicsCount ; i++ ) {
    if (strcmp(this->inTopics[i], topic) == 0) { //I'm listening this topic, so I need to get to work
      this->doHandle(topic, payload, length);
      return true;
    }
  }
  return false;
};

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "types.hh"
#include "bytes.hh"

#include <optional>
#include <variant>

#include <seastar/util/variant_utils.hh>

#include "utils/fragmented_temporary_buffer.hh"

namespace cql3 {

struct null_value {
};

struct unset_value {
};

/// \brief View to a raw CQL protocol value.
///
/// \see raw_value
struct raw_value_view {
    std::variant<fragmented_temporary_buffer::view, null_value, unset_value> _data;

    raw_value_view(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(fragmented_temporary_buffer::view data)
        : _data{data}
    {}
public:
    static raw_value_view make_null() {
        return raw_value_view{std::move(null_value{})};
    }
    static raw_value_view make_unset_value() {
        return raw_value_view{std::move(unset_value{})};
    }
    static raw_value_view make_value(fragmented_temporary_buffer::view view) {
        return raw_value_view{view};
    }
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<fragmented_temporary_buffer::view>(_data);
    }
    std::optional<fragmented_temporary_buffer::view> data() const {
        if (auto pdata = std::get_if<fragmented_temporary_buffer::view>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const fragmented_temporary_buffer::view* operator->() const {
        return &std::get<fragmented_temporary_buffer::view>(_data);
    }
    const fragmented_temporary_buffer::view& operator*() const {
        return std::get<fragmented_temporary_buffer::view>(_data);
    }

    bool operator==(const raw_value_view& other) const {
        if (_data.index() != other._data.index()) {
            return false;
        }
        if (is_value() && **this != *other) {
            return false;
        }
        return true;
    }
    bool operator!=(const raw_value_view& other) const {
        return !(*this == other);
    }

    friend std::ostream& operator<<(std::ostream& os, const raw_value_view& value);
};

/// \brief Raw CQL protocol value.
///
/// The `raw_value` type represents an uninterpreted value from the CQL wire
/// protocol. A raw value can hold either a null value, an unset value, or a byte
/// blob that represents the value.
class raw_value {
    std::variant<bytes, null_value, unset_value> _data;

    raw_value(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(bytes&& data)
        : _data{std::move(data)}
    {}
    raw_value(const bytes& data)
        : _data{data}
    {}
public:
    static raw_value make_null() {
        return raw_value{std::move(null_value{})};
    }
    static raw_value make_unset_value() {
        return raw_value{std::move(unset_value{})};
    }
    static raw_value make_value(const raw_value_view& view);
    static raw_value make_value(bytes&& bytes) {
        return raw_value{std::move(bytes)};
    }
    static raw_value make_value(const bytes& bytes) {
        return raw_value{bytes};
    }
    static raw_value make_value(const bytes_opt& bytes) {
        if (bytes) {
            return make_value(*bytes);
        }
        return make_null();
    }
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<bytes>(_data);
    }
    bytes_opt data() const {
        if (auto pdata = std::get_if<bytes>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const bytes* operator->() const {
        return &std::get<bytes>(_data);
    }
    const bytes& operator*() const {
        return std::get<bytes>(_data);
    }
    raw_value_view to_view() const;
};

}

inline bytes to_bytes(const cql3::raw_value_view& view)
{
    return linearized(*view);
}

inline bytes_opt to_bytes_opt(const cql3::raw_value_view& view) {
    auto buffer_view = view.data();
    if (buffer_view) {
        return bytes_opt(linearized(*buffer_view));
    }
    return bytes_opt();
}

inline bytes_opt to_bytes_opt(const cql3::raw_value& value) {
    return to_bytes_opt(value.to_view());
}
<commit_msg>cql3: allow moving data out of raw_value<commit_after>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "types.hh"
#include "bytes.hh"

#include <optional>
#include <variant>

#include <seastar/util/variant_utils.hh>

#include "utils/fragmented_temporary_buffer.hh"

namespace cql3 {

struct null_value {
};

struct unset_value {
};

/// \brief View to a raw CQL protocol value.
///
/// \see raw_value
struct raw_value_view {
    std::variant<fragmented_temporary_buffer::view, null_value, unset_value> _data;

    raw_value_view(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(fragmented_temporary_buffer::view data)
        : _data{data}
    {}
public:
    static raw_value_view make_null() {
        return raw_value_view{std::move(null_value{})};
    }
    static raw_value_view make_unset_value() {
        return raw_value_view{std::move(unset_value{})};
    }
    static raw_value_view make_value(fragmented_temporary_buffer::view view) {
        return raw_value_view{view};
    }
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<fragmented_temporary_buffer::view>(_data);
    }
    std::optional<fragmented_temporary_buffer::view> data() const {
        if (auto pdata = std::get_if<fragmented_temporary_buffer::view>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const fragmented_temporary_buffer::view* operator->() const {
        return &std::get<fragmented_temporary_buffer::view>(_data);
    }
    const fragmented_temporary_buffer::view& operator*() const {
        return std::get<fragmented_temporary_buffer::view>(_data);
    }

    bool operator==(const raw_value_view& other) const {
        if (_data.index() != other._data.index()) {
            return false;
        }
        if (is_value() && **this != *other) {
            return false;
        }
        return true;
    }
    bool operator!=(const raw_value_view& other) const {
        return !(*this == other);
    }

    friend std::ostream& operator<<(std::ostream& os, const raw_value_view& value);
};

/// \brief Raw CQL protocol value.
///
/// The `raw_value` type represents an uninterpreted value from the CQL wire
/// protocol. A raw value can hold either a null value, an unset value, or a byte
/// blob that represents the value.
class raw_value {
    std::variant<bytes, null_value, unset_value> _data;

    raw_value(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(bytes&& data)
        : _data{std::move(data)}
    {}
    raw_value(const bytes& data)
        : _data{data}
    {}
public:
    static raw_value make_null() {
        return raw_value{std::move(null_value{})};
    }
    static raw_value make_unset_value() {
        return raw_value{std::move(unset_value{})};
    }
    static raw_value make_value(const raw_value_view& view);
    static raw_value make_value(bytes&& bytes) {
        return raw_value{std::move(bytes)};
    }
    static raw_value make_value(const bytes& bytes) {
        return raw_value{bytes};
    }
    static raw_value make_value(const bytes_opt& bytes) {
        if (bytes) {
            return make_value(*bytes);
        }
        return make_null();
    }
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<bytes>(_data);
    }
    bytes_opt data() const {
        if (auto pdata = std::get_if<bytes>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const bytes* operator->() const {
        return &std::get<bytes>(_data);
    }
    const bytes& operator*() const {
        return std::get<bytes>(_data);
    }
    bytes&& extract_value() && {
        auto b = std::get_if<bytes>(&_data);
        assert(b);
        return std::move(*b);
    }
    raw_value_view to_view() const;
};

}

inline bytes to_bytes(const cql3::raw_value_view& view)
{
    return linearized(*view);
}

inline bytes_opt to_bytes_opt(const cql3::raw_value_view& view) {
    auto buffer_view = view.data();
    if (buffer_view) {
        return bytes_opt(linearized(*buffer_view));
    }
    return bytes_opt();
}

inline bytes_opt to_bytes_opt(const cql3::raw_value& value) {
    return to_bytes_opt(value.to_view());
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>
using namespace std;

enum class Token
{
	Invalid,
	Minus,
	Plus,
	Mul,
	Div,
	Number,
	End
};

Token getToken(const char*& text, bool reverse = false, const char* limit = 0)
{
	// function for parsing tokens
	//
	//    text: the starting point
	// reverse: whether to move forward or backwards
	//   limit: the point to stop at when moving backwards

	while (const auto c = *text)
	{
		if (limit && reverse && (text <= limit))
			break;

		reverse ? (--text) : (++text);

		switch (c)
		{
			case ' ': continue;
			case '-': return Token::Minus;
			case '+': return Token::Plus;
			case '*': return Token::Mul;
			case '/': return Token::Div;
		}

		if (c >= '1' && c <= '9')
		{
			for (auto c = *text; c >= '0' && c <= '9';)
				{
					reverse ? (--text) : (++text);
					if (limit && reverse && (text <= limit))
						break;
					c = *text;
				}
			return Token::Number;
		}
		return Token::Invalid;
	}
	return Token::End;

}

int number(const char* start, const char* end)
{

	// function for parsing numbers
	int result = 0;
	int sign = 1;

	//ignore trailing minus
	if (*end == '-')
		--end;

	while (start <= end){
		if (*start != ' '){
			if (*start == '-'){
				sign *= -1;
			} else {
				if (*start >= '0' && *start <= '9')
					result = result * 10 + *start - 48;
			}
		}
		++start;
	}
	return sign * result;

}

int term(const char* start, const char* end)
{
	// function for parsing terms

	// function invariant: start <= ptr1 <= ptr2 <= end
	// current token is between ptr1 and ptr2

	if (start == end)
		return number(start, end);
	const char* ptr1 = end;
	const char* ptr2 = end;

	while (ptr1 > start){
		// explanation why the pointer moves backwards is in the readme
		auto token = getToken(ptr1, true, start);
		if (token == Token::Mul)
		{
			return term(start, ptr1) * number(ptr2, end);
		} else if (token == Token::Div) {
			int denominator = number(ptr2, end);
			if (not denominator)
				throw std::overflow_error("Exception: zero division");
			return term(start, ptr1) / denominator;
		}
		if (ptr1 == ptr2)
			--ptr1;
		ptr2 = ptr1;
	}

	return number(start, end);

}

int expr(const char* start, const char* end)
{
	// function for parsing expressions

	// function invariant: start <= ptr1 <= ptr2 <= end
	// current token is between ptr1 and ptr2

	if (start >= end)
		return 0;

	// binaryMinus is needed to understand if we need to split the expression
	bool binaryMinus = false;
	const char* ptr1 = start;
	const char* ptr2 = start;

	while (ptr2 < end){
		auto token = getToken(ptr2);

		if (token == Token::Plus) {
			return term(start, ptr1) + expr(ptr2, end);
		} else if ((token == Token::Minus) && binaryMinus){
			return term(start, ptr1) + expr(ptr1, end);
		}

		binaryMinus = (token == Token::Number) ? true : false;
		ptr1 = ptr2;
	}
	return term(start, end);

}

int main(int argc, char const *argv[])
{
	if (argc == 1){
		cout << "No expression provided";
		return 1;
	}
	const char* start = argv[1];
	const char* end = start;
	bool invalid = false;
	bool NAN = true;

	auto token = getToken(end);
	while (token != Token::End)
	{
		switch (token)
		{
			case Token::Invalid: {
				invalid = true;
				break;
			}
			case Token::Number: {
				if (not NAN)
					invalid = true;
				NAN = false;
				break;
			}
			case Token::Minus: {
				NAN = true;
				break;
			}
			default: {
				if (NAN)
					invalid = true;
				NAN = true;
			}
		}
		if (invalid)
			break;
		token = getToken(end);
	}

	if (invalid || NAN){
		cout << "Invalid expression";
		return 1;
	} else {
		try {
	    	cout << expr(start, end);
	    } catch (std::overflow_error e) {
	        std::cout << e.what();
	        return 1;
	    }
	}
	return 0;

}<commit_msg>Koshman hw02: fixed numbers starting with 0<commit_after>#include <iostream>
#include <stdexcept>
using namespace std;

enum class Token
{
	Invalid,
	Minus,
	Plus,
	Mul,
	Div,
	Number,
	End
};

Token getToken(const char*& text, bool reverse = false, const char* limit = 0)
{
	// function for parsing tokens
	//
	//    text: the starting point
	// reverse: whether to move forward or backwards
	//   limit: the point to stop at when moving backwards

	while (const auto c = *text)
	{
		if (limit && reverse && (text <= limit))
			break;

		reverse ? (--text) : (++text);

		switch (c)
		{
			case ' ': continue;
			case '-': return Token::Minus;
			case '+': return Token::Plus;
			case '*': return Token::Mul;
			case '/': return Token::Div;
			case '0': return Token::Number;
		}

		if (c >= '1' && c <= '9')
		{
			for (auto c = *text; c >= '0' && c <= '9';)
				{
					reverse ? (--text) : (++text);
					if (limit && reverse && (text <= limit))
						break;
					c = *text;
				}
			return Token::Number;
		}
		return Token::Invalid;
	}
	return Token::End;

}

int number(const char* start, const char* end)
{

	// function for parsing numbers
	int result = 0;
	int sign = 1;

	//ignore trailing minus
	if (*end == '-')
		--end;

	while (start <= end){
		if (*start != ' '){
			if (*start == '-'){
				sign *= -1;
			} else {
				if (*start >= '0' && *start <= '9')
					result = result * 10 + *start - 48;
			}
		}
		++start;
	}
	return sign * result;

}

int term(const char* start, const char* end)
{
	// function for parsing terms

	// function invariant: start <= ptr1 <= ptr2 <= end
	// current token is between ptr1 and ptr2

	if (start == end)
		return number(start, end);
	const char* ptr1 = end;
	const char* ptr2 = end;

	while (ptr1 > start){
		// explanation why the pointer moves backwards is in the readme
		auto token = getToken(ptr1, true, start);
		if (token == Token::Mul)
		{
			return term(start, ptr1) * number(ptr2, end);
		} else if (token == Token::Div) {
			int denominator = number(ptr2, end);
			if (not denominator)
				throw std::overflow_error("Exception: zero division");
			return term(start, ptr1) / denominator;
		}
		if (ptr1 == ptr2)
			--ptr1;
		ptr2 = ptr1;
	}

	return number(start, end);

}

int expr(const char* start, const char* end)
{
	// function for parsing expressions

	// function invariant: start <= ptr1 <= ptr2 <= end
	// current token is between ptr1 and ptr2

	if (start >= end)
		return 0;

	// binaryMinus is needed to understand if we need to split the expression
	bool binaryMinus = false;
	const char* ptr1 = start;
	const char* ptr2 = start;

	while (ptr2 < end){
		auto token = getToken(ptr2);

		if (token == Token::Plus) {
			return term(start, ptr1) + expr(ptr2, end);
		} else if ((token == Token::Minus) && binaryMinus){
			return term(start, ptr1) + expr(ptr1, end);
		}

		binaryMinus = (token == Token::Number) ? true : false;
		ptr1 = ptr2;
	}
	return term(start, end);

}

int main(int argc, char const *argv[])
{
	if (argc == 1){
		cout << "No expression provided";
		return 1;
	}
	const char* start = argv[1];
	const char* end = start;
	bool invalid = false;
	bool NAN = true;

	auto token = getToken(end);
	while (token != Token::End)
	{
		switch (token)
		{
			case Token::Invalid: {
				invalid = true;
				break;
			}
			case Token::Number: {
				if (not NAN)
					invalid = true;
				NAN = false;
				break;
			}
			case Token::Minus: {
				NAN = true;
				break;
			}
			default: {
				if (NAN)
					invalid = true;
				NAN = true;
			}
		}
		if (invalid)
			break;
		token = getToken(end);
	}

	if (invalid || NAN){
		cout << "Invalid expression";
		return 1;
	} else {
		try {
	    	cout << expr(start, end);
	    } catch (std::overflow_error e) {
	        std::cout << e.what();
	        return 1;
	    }
	}
	return 0;

}<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <windows.h>
#elif   qPlatform_POSIX
#include    <dirent.h>
#endif

#include    "../../Debug/Trace.h"
#include    "../../Execution/ErrNoException.h"
#if     qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#endif
#include    "../../IO/FileAccessException.h"

#include    "DirectoryIterator.h"

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;
using   namespace   Stroika::Foundation::Traversal;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
#endif
using   Execution::ThrowIfError_errno_t;

class   DirectoryIterator::Rep_ : public Iterator<String>::IRep {
private:
#if     qPlatform_Windows
    String          fDirName_;
    HANDLE          fHandle_            { INVALID_HANDLE_VALUE };
    WIN32_FIND_DATA fFindFileData_;
    int             fSeekOffset_        { 0 };
#elif   qPlatform_POSIX
    DIR*            fDirIt_             { nullptr };
    dirent          fDirEntBuf_;        // intentionally uninitialized (done by readdir)
    dirent*         fCur_               { nullptr };
#endif

public:
    Rep_ (const String& dir)
#if     qPlatform_Windows
        : fDirName_ (dir)
#elif   qPlatform_POSIX
        : fDirIt_ { ::opendir (dir.AsSDKString ().c_str ()) }
#endif
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::CTOR('%s')", dir.c_str ());
#endif
        try {
#if     qPlatform_Windows
            (void)::memset (&fFindFileData_, 0, sizeof (fFindFileData_));
            fHandle_ = ::FindFirstFile ((dir + L"\\*").AsSDKString ().c_str (), &fFindFileData_);
#elif   qPlatform_POSIX
            if (fDirIt_ == nullptr)
            {
                Execution::ThrowIfError_errno_t ();
            }
            else {
                ThrowIfError_errno_t (::readdir_r (fDirIt_, &fDirEntBuf_, &fCur_));
                Assert (fCur_ == nullptr or fCur_ == &fDirEntBuf_);
            }
#endif
        }
        Stroika_Foundation_IO_FileAccessException_CATCH_REBIND_FILENAMESONLY_HELPER(dir);
    }
#if     qPlatform_Windows
    Rep_ (const String& dir, int seekPos)
        : fDirName_ (dir)
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::CTOR('%s',seekPos=%d)", dir.c_str (), seekPos);
#endif
        (void)::memset (&fFindFileData_, 0, sizeof (fFindFileData_));
        fHandle_ = ::FindFirstFile ((dir + L"\\*").AsSDKString ().c_str (), &fFindFileData_);
        for (int i = 0; i < seekPos; ++i) {
            if (::FindNextFile (fHandle_, &fFindFileData_) == 0) {
                ::FindClose (fHandle_);
                fHandle_ = INVALID_HANDLE_VALUE;
            }
            else {
                fSeekOffset_++;
            }
        }
    }
#elif   qPlatform_POSIX
    Rep_ (DIR* dirObj)
        : fDirIt_ { dirObj } {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::CTOR(dirObj=%x)", int(dirObj));
#endif
        if (fDirIt_ != nullptr)
        {
            ThrowIfError_errno_t (::readdir_r (fDirIt_, &fDirEntBuf_, &fCur_));
            Assert (fCur_ == nullptr or fCur_ == &fDirEntBuf_);
        }
    }
#endif
    virtual ~Rep_ ()
    {
#if         qPlatform_Windows
        if (fHandle_ != INVALID_HANDLE_VALUE) {
            ::FindClose (fHandle_);
        }
#elif   qPlatform_POSIX
        if (fDirIt_ != nullptr) {
            ::closedir (fDirIt_);
        }
#endif
    }
    virtual void    More (Memory::Optional<String>* result, bool advance) override
    {
        RequireNotNull (result);
        result->clear ();
#if     qPlatform_Windows
        if (advance) {
            Require (fHandle_ != INVALID_HANDLE_VALUE);
            memset (&fFindFileData_, 0, sizeof (fFindFileData_));
            if (::FindNextFile (fHandle_, &fFindFileData_) == 0) {
                ::FindClose (fHandle_);
                fHandle_ = INVALID_HANDLE_VALUE;
            }
        }
        if (fHandle_ != INVALID_HANDLE_VALUE) {
            *result = String::FromSDKString (fFindFileData_.cFileName);
        }
#elif   qPlatform_POSIX
        if (advance) {
            RequireNotNull (fCur_);
            RequireNotNull (fDirIt_);
            ThrowIfError_errno_t (::readdir_r (fDirIt_, &fDirEntBuf_, &fCur_));
            Assert (fCur_ == nullptr or fCur_ == &fDirEntBuf_);
        }
        if (fCur_ != nullptr) {
            *result = String::FromSDKString (fCur_->d_name);
        }
#endif
    }
    virtual bool    Equals (const Iterator<String>::IRep* rhs) const override
    {
        RequireNotNull (rhs);
        RequireMember (rhs, Rep_);
        const Rep_&  rrhs = *dynamic_cast<const Rep_*> (rhs);
#if     qPlatform_Windows
        return fHandle_ == rrhs.fHandle_;
#elif   qPlatform_POSIX
        return fDirIt_ == rrhs.fDirIt_;
#endif
    }
    virtual SharedIRepPtr    Clone () const override
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::Clone");
#endif
#if     qPlatform_Windows
        return SharedIRepPtr (MakeSharedPtr<Rep_> (fDirName_, fSeekOffset_));
#elif   qPlatform_POSIX
        if (fDirIt_ == nullptr) {
            return SharedIRepPtr (MakeSharedPtr<Rep_> (nullptr));
        }
        /*
         *  must find telldir() returns the location of the NEXT read. We must pass along the value of telldir as
         *  of the PREVIOUS read. Essentially (seek CUR_OFF, -1);
         *
         *  But - this API doesn't support that.
         *
         *  This leaves us with several weak alternatives:
         *      o   save the telldir, and seek to the start of the dir, and repeatedly seek until
         *          we get the same telldir, and then return the previous stored value.
         *
         *      o   substract 1 from the value of telldir()
         *
         *      o   Before each 'readdir() - do a telldir() to capture its value.
         *
         *      o   When cloning - compute offset in file#s by rewinding and seeking til we find the same value by
         *          name or some such, and then use that same process to re-seek in the cloned dirEnt.
         *
         *  The 'subtract 1' approach, though cheap and simple, appears not supported by the telldir documentation,
         *  and looking at values in the current linux/gcc, seems unpromising.
         *
         *  Between the 'telldir' before each read, and re-seek approaches, the former adds overhead even when not cloning
         *  iterators, and the later only when you use the feature. Moreover, the seek-to-start and keep looking
         *  for telldir() approach probably works out efficeintly, as the most likely time to Clone () an iterator is
         *  when it is 'at start' anyhow (DirectoryIterable). So we'll start with that...
         *          -- LGP 2014-07-10
         */
        // Note - NOT 100% sure its OK to look for identical value telldir in another dir...
        DIR*        dirObj          =   ::fdopendir (::dirfd (fDirIt_));
        dirent      dirEntBuf;      // intentionally uninitialized (done by readdir)
        if (fCur_ == nullptr) {
            // then we're past end end, the cloned fdopen dir one SB too!
            dirent* d = nullptr;
            dirent  db;// no init on purpose
            (void)::readdir_r (fDirIt_, &db, &d);
            Assert (d == nullptr);
        }
        else {
            ino_t   aBridgeTooFar   =   fCur_->d_ino;
            ::rewinddir (dirObj);
            long useOffset = ::telldir (dirObj);
            for (;;) {
                //dirent* tmp = ::readdir (dirObj);
                dirent* tmp = nullptr;
                // ThrowIfError_errno_t (::readdir_r (dirObj, &dirEntBuf, &tmp));        // @todo UNSURE if we want to check error here?
                ::readdir_r (dirObj, &dirEntBuf, &tmp);
                Assert (tmp == nullptr or tmp == &dirEntBuf);
                if (tmp == nullptr) {
                    // somehow the file went away, so no idea where to start, and the end is as reasonable as anywhere else???
                    useOffset = ::telldir (dirObj);
                    DbgTrace (L"WARN: possible bug? - ususual, and not handled well, but this can happen if the file disappears while we're cloning");
                    break;
                }
                else if (tmp->d_ino == aBridgeTooFar) {
                    // then we are now pointing at the right elt, and want to seek to the PRECEEDING one so when it does a readdir it gets that item
                    // so DONT update useOffset - just break!
                    break;
                }
                else {
                    // update to this reflects the last offset before we find d_ino
                    useOffset = ::telldir (dirObj);
                }
            }
            ::seekdir (dirObj, useOffset);
        }
        return SharedIRepPtr (MakeSharedPtr<Rep_> (dirObj));
#endif
    }
    virtual IteratorOwnerID GetOwner () const override
    {
        /*
         *  This return value allows any two DiscreteRange iterators (of the same type) to be compared.
         */
        return typeid (*this).name ();
    }
};

/*
 ********************************************************************************
 ******************** IO::FileSystem::DirectoryIterator *************************
 ********************************************************************************
 */
DirectoryIterator::DirectoryIterator (const String& directoryName)
    : Iterator<String> (Iterator<String>::SharedIRepPtr (MakeSharedPtr<Rep_> (directoryName)))
{
}
<commit_msg>allow EBADF and dont throw on iterator - appears legal by docs (unclear) and happens on AIX at EOF. Just add asserts<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <windows.h>
#elif   qPlatform_POSIX
#include    <dirent.h>
#endif

#include    "../../Debug/Trace.h"
#include    "../../Execution/ErrNoException.h"
#if     qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#endif
#include    "../../IO/FileAccessException.h"

#include    "DirectoryIterator.h"

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;
using   namespace   Stroika::Foundation::Traversal;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
#endif
using   Execution::ThrowIfError_errno_t;

class   DirectoryIterator::Rep_ : public Iterator<String>::IRep {
private:
#if     qPlatform_Windows
    String          fDirName_;
    HANDLE          fHandle_            { INVALID_HANDLE_VALUE };
    WIN32_FIND_DATA fFindFileData_;
    int             fSeekOffset_        { 0 };
#elif   qPlatform_POSIX
    DIR*            fDirIt_             { nullptr };
    dirent          fDirEntBuf_;        // intentionally uninitialized (done by readdir)
    dirent*         fCur_               { nullptr };
#endif

public:
    Rep_ (const String& dir)
#if     qPlatform_Windows
        : fDirName_ (dir)
#elif   qPlatform_POSIX
        : fDirIt_ { ::opendir (dir.AsSDKString ().c_str ()) }
#endif
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::CTOR('%s')", dir.c_str ());
#endif
        try {
#if     qPlatform_Windows
            (void)::memset (&fFindFileData_, 0, sizeof (fFindFileData_));
            fHandle_ = ::FindFirstFile ((dir + L"\\*").AsSDKString ().c_str (), &fFindFileData_);
#elif   qPlatform_POSIX
            if (fDirIt_ == nullptr)
            {
                Execution::ThrowIfError_errno_t ();
            }
            else {
                ThrowIfError_errno_t (::readdir_r (fDirIt_, &fDirEntBuf_, &fCur_));
                Assert (fCur_ == nullptr or fCur_ == &fDirEntBuf_);
            }
#endif
        }
        Stroika_Foundation_IO_FileAccessException_CATCH_REBIND_FILENAMESONLY_HELPER(dir);
    }
#if     qPlatform_Windows
    Rep_ (const String& dir, int seekPos)
        : fDirName_ (dir)
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::CTOR('%s',seekPos=%d)", dir.c_str (), seekPos);
#endif
        (void)::memset (&fFindFileData_, 0, sizeof (fFindFileData_));
        fHandle_ = ::FindFirstFile ((dir + L"\\*").AsSDKString ().c_str (), &fFindFileData_);
        for (int i = 0; i < seekPos; ++i) {
            if (::FindNextFile (fHandle_, &fFindFileData_) == 0) {
                ::FindClose (fHandle_);
                fHandle_ = INVALID_HANDLE_VALUE;
            }
            else {
                fSeekOffset_++;
            }
        }
    }
#elif   qPlatform_POSIX
    Rep_ (DIR* dirObj)
        : fDirIt_ { dirObj } {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::CTOR(dirObj=%x)", int(dirObj));
#endif
        if (fDirIt_ != nullptr)
        {
            ThrowIfError_errno_t (::readdir_r (fDirIt_, &fDirEntBuf_, &fCur_));
            Assert (fCur_ == nullptr or fCur_ == &fDirEntBuf_);
        }
    }
#endif
    virtual ~Rep_ ()
    {
#if         qPlatform_Windows
        if (fHandle_ != INVALID_HANDLE_VALUE) {
            ::FindClose (fHandle_);
        }
#elif   qPlatform_POSIX
        if (fDirIt_ != nullptr) {
            ::closedir (fDirIt_);
        }
#endif
    }
    virtual void    More (Memory::Optional<String>* result, bool advance) override
    {
        RequireNotNull (result);
        result->clear ();
#if     qPlatform_Windows
        if (advance) {
            Require (fHandle_ != INVALID_HANDLE_VALUE);
            memset (&fFindFileData_, 0, sizeof (fFindFileData_));
            if (::FindNextFile (fHandle_, &fFindFileData_) == 0) {
                ::FindClose (fHandle_);
                fHandle_ = INVALID_HANDLE_VALUE;
            }
        }
        if (fHandle_ != INVALID_HANDLE_VALUE) {
            *result = String::FromSDKString (fFindFileData_.cFileName);
        }
#elif   qPlatform_POSIX
        if (advance) {
            RequireNotNull (fCur_);
            RequireNotNull (fDirIt_);
            errno_t e = ::readdir_r (fDirIt_, &fDirEntBuf_, &fCur_);
            if (e == EBADF) {
                Assert (fCur_ == nullptr );
            }
            else {
                ThrowIfError_errno_t (e);
            }
            Assert (fCur_ == nullptr or fCur_ == &fDirEntBuf_);
        }
        if (fCur_ != nullptr) {
            *result = String::FromSDKString (fCur_->d_name);
        }
#endif
    }
    virtual bool    Equals (const Iterator<String>::IRep* rhs) const override
    {
        RequireNotNull (rhs);
        RequireMember (rhs, Rep_);
        const Rep_&  rrhs = *dynamic_cast<const Rep_*> (rhs);
#if     qPlatform_Windows
        return fHandle_ == rrhs.fHandle_;
#elif   qPlatform_POSIX
        return fDirIt_ == rrhs.fDirIt_;
#endif
    }
    virtual SharedIRepPtr    Clone () const override
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Entering DirectoryIterator::Rep_::Clone");
#endif
#if     qPlatform_Windows
        return SharedIRepPtr (MakeSharedPtr<Rep_> (fDirName_, fSeekOffset_));
#elif   qPlatform_POSIX
        if (fDirIt_ == nullptr) {
            return SharedIRepPtr (MakeSharedPtr<Rep_> (nullptr));
        }
        /*
         *  must find telldir() returns the location of the NEXT read. We must pass along the value of telldir as
         *  of the PREVIOUS read. Essentially (seek CUR_OFF, -1);
         *
         *  But - this API doesn't support that.
         *
         *  This leaves us with several weak alternatives:
         *      o   save the telldir, and seek to the start of the dir, and repeatedly seek until
         *          we get the same telldir, and then return the previous stored value.
         *
         *      o   substract 1 from the value of telldir()
         *
         *      o   Before each 'readdir() - do a telldir() to capture its value.
         *
         *      o   When cloning - compute offset in file#s by rewinding and seeking til we find the same value by
         *          name or some such, and then use that same process to re-seek in the cloned dirEnt.
         *
         *  The 'subtract 1' approach, though cheap and simple, appears not supported by the telldir documentation,
         *  and looking at values in the current linux/gcc, seems unpromising.
         *
         *  Between the 'telldir' before each read, and re-seek approaches, the former adds overhead even when not cloning
         *  iterators, and the later only when you use the feature. Moreover, the seek-to-start and keep looking
         *  for telldir() approach probably works out efficeintly, as the most likely time to Clone () an iterator is
         *  when it is 'at start' anyhow (DirectoryIterable). So we'll start with that...
         *          -- LGP 2014-07-10
         */
        // Note - NOT 100% sure its OK to look for identical value telldir in another dir...
        DIR*        dirObj          =   ::fdopendir (::dirfd (fDirIt_));
        dirent      dirEntBuf;      // intentionally uninitialized (done by readdir)
        if (fCur_ == nullptr) {
            // then we're past end end, the cloned fdopen dir one SB too!
            dirent* d = nullptr;
            dirent  db;// no init on purpose
            (void)::readdir_r (fDirIt_, &db, &d);
            Assert (d == nullptr);
        }
        else {
            ino_t   aBridgeTooFar   =   fCur_->d_ino;
            ::rewinddir (dirObj);
            long useOffset = ::telldir (dirObj);
            for (;;) {
                //dirent* tmp = ::readdir (dirObj);
                dirent* tmp = nullptr;
                // ThrowIfError_errno_t (::readdir_r (dirObj, &dirEntBuf, &tmp));        // @todo UNSURE if we want to check error here?
                ::readdir_r (dirObj, &dirEntBuf, &tmp);
                Assert (tmp == nullptr or tmp == &dirEntBuf);
                if (tmp == nullptr) {
                    // somehow the file went away, so no idea where to start, and the end is as reasonable as anywhere else???
                    useOffset = ::telldir (dirObj);
                    DbgTrace (L"WARN: possible bug? - ususual, and not handled well, but this can happen if the file disappears while we're cloning");
                    break;
                }
                else if (tmp->d_ino == aBridgeTooFar) {
                    // then we are now pointing at the right elt, and want to seek to the PRECEEDING one so when it does a readdir it gets that item
                    // so DONT update useOffset - just break!
                    break;
                }
                else {
                    // update to this reflects the last offset before we find d_ino
                    useOffset = ::telldir (dirObj);
                }
            }
            ::seekdir (dirObj, useOffset);
        }
        return SharedIRepPtr (MakeSharedPtr<Rep_> (dirObj));
#endif
    }
    virtual IteratorOwnerID GetOwner () const override
    {
        /*
         *  This return value allows any two DiscreteRange iterators (of the same type) to be compared.
         */
        return typeid (*this).name ();
    }
};

/*
 ********************************************************************************
 ******************** IO::FileSystem::DirectoryIterator *************************
 ********************************************************************************
 */
DirectoryIterator::DirectoryIterator (const String& directoryName)
    : Iterator<String> (Iterator<String>::SharedIRepPtr (MakeSharedPtr<Rep_> (directoryName)))
{
}
<|endoftext|>