<commit_before>// Copyright (c) 2016 Kasper Kronborg Isager and Radoslaw Niemczyk.
#include "vector.hpp"

#include <iostream>

namespace lsh {
  /**
   * Create a new vector from existing component chunks.
   *
   * @param components The existing component chunks.
   * @param size The number of components.
   */
  vector::vector(const std::vector<unsigned int>& components, unsigned int size) {
    this->size_ = size;

    unsigned int n = components.size();

    for (unsigned int i = 0; i < n; i++) {
      this->components_.push_back(components[i]);
    }
  }

  /**
   * Construct a new vector.
   *
   * @param components The components of the vector.
   */
  vector::vector(const std::vector<bool>& components) {
    this->size_ = components.size();

    unsigned int s = this->size_;
    unsigned int c = this->chunk_size_;
    unsigned int i = 0;
    unsigned int k = 0;

    while (i < s) {
      this->components_.push_back(0);

      // Compute the number of bits in the current chunk.
      unsigned int b = i + c > s ? s - i : c;

      for (unsigned int j = 0; j < b; j++) {
        this->components_[k] |= components[i + j] << (b - j - 1);
      }

      i += b;
      k += 1;
    }
  }

  /**
   * Get the number of components in this vector.
   *
   * @return The number of components in this vector.
   */
  unsigned int vector::size() const {
    return this->size_;
  }

  /**
   * Get the component at the specified index of this vector.
   *
   * @param index The index of the component to get.
   * @return The component at the index.
   */
  bool vector::get(unsigned int index) const {
    unsigned int s = this->size_;
    unsigned int c = this->chunk_size_;

    if (index >= s) {
      throw std::out_of_range("Invalid index");
    }

    // Compute the index of the target chunk.
    unsigned int d = index / s;

    // Compute the index of the first bit of the target chunk.
    unsigned int j = d * s;

    // Compute the number of bits in the target chunk.
    unsigned int b = j + c > s ? s - j : c;

    return (this->components_[d] >> (b - (index % s) - 1)) & 1;
  }

  /**
   * Get a string representation of this vector.
   *
   * @return The string representation of the vector.
   */
  std::string vector::to_string() const {
    unsigned int n = this->size_;

    std::string value = "Vector[";

    for (unsigned int i = 0; i < n; i++) {
      value += std::to_string(this->get(i));
    }

    return value + "]";
  }

  /**
   * Check if this vector equals another vector.
   *
   * @param vector The other vector.
   * @return `true` if this vector equals the other vector, otherwise `false`.
   */
  bool vector::operator==(const vector& vector) const {
    if (this->size() != vector.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    return vector::distance(*this, vector) == 0;
  }

  /**
   * Compute the dot product of this and another vector.
   *
   * @param vector The other vector.
   * @return The dot product of this and another vector.
   */
  unsigned int vector::operator*(const vector& vector) const {
    if (this->size() != vector.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    unsigned int d = 0;
    unsigned int n = this->components_.size();

    for (unsigned int i = 0; i < n; i++) {
      d += __builtin_popcount(this->components_[i] & vector.components_[i]);
    }

    return d;
  }

  /**
   * Compute the dot product of this vector and an integer.
   *
   * @param integer The integer.
   * @return The dot product of this vector and an integer.
   */
  unsigned int vector::operator*(unsigned int integer) const {
    unsigned int d = 0;
    unsigned int s = this->size_;
    unsigned int c = this->chunk_size_;
    unsigned int n = this->components_.size();

    for (unsigned int i = 0; i < n; i++) {
      // Compute the index of the first bit of the current chunk.
      unsigned int j = c * i;

      // Compute the number of bits in the current chunk.
      unsigned int m = j + c > s ? s - j : c;

      // Grab the bits of the integer that correspond to the current chunk.
      unsigned int b = (integer >> (s - j - m)) % (1 << m);

      d += __builtin_popcount(this->components_[i] & b);
    }

    return d;
  }

  /**
   * Compute the bitwise AND of this and another vector.
   *
   * @param vector The other vector.
   * @return The bitwise AND of this and another vector.
   */
  vector vector::operator&(const vector& vector) const {
    if (this->size() != vector.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    std::vector<unsigned int> c;

    unsigned int n = this->components_.size();

    for (unsigned int i = 0; i < n; i++) {
      c.push_back(this->components_[i] & vector.components_[i]);
    }

    return lsh::vector(c, this->size_);
  }

  /**
   * Compupte the hash of this vector.
   *
   * @return The hash of this vector.
   */
  int vector::hash() const {
    unsigned int n = this->components_.size();
    unsigned long h = 7;

    for (unsigned int i = 0; i < n; i++) {
      h = 31 * h + this->components_[i];
    }

    return h ^ (h >> 32);
  }

  /**
   * Compute the distance between two vectors.
   *
   * @see http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
   *
   * @param u The first vector.
   * @param v The second vector.
   * @return The distance between the two vectors.
   */
  int vector::distance(const vector& u, const vector& v) {
    if (u.size() != v.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    unsigned int d = 0;
    unsigned int n = u.components_.size();

    for (unsigned int i = 0; i < n; i++) {
      unsigned int x = u.components_[i] ^ v.components_[i];

      while (x) {
        x &= x - 1;
        d++;
      }
    }

    return d;
  }

  /**
   * Construct a random vector of a given dimensionality.
   *
   * @param dimensions The number of dimensions in the vector.
   * @return The randomly generated vector.
   */
  vector vector::random(unsigned int dimensions) {
    std::random_device random;
    std::mt19937 generator(random());
    std::uniform_int_distribution<> components(0, 1);

    std::vector<bool> c;

    for (unsigned int i = 0; i < dimensions; i++) {
      c.push_back(components(generator));
    }

    return vector(c);
  }
}
<commit_msg>Remove bad include<commit_after>// Copyright (c) 2016 Kasper Kronborg Isager and Radoslaw Niemczyk.
#include "vector.hpp"

namespace lsh {
  /**
   * Create a new vector from existing component chunks.
   *
   * @param components The existing component chunks.
   * @param size The number of components.
   */
  vector::vector(const std::vector<unsigned int>& components, unsigned int size) {
    this->size_ = size;

    unsigned int n = components.size();

    for (unsigned int i = 0; i < n; i++) {
      this->components_.push_back(components[i]);
    }
  }

  /**
   * Construct a new vector.
   *
   * @param components The components of the vector.
   */
  vector::vector(const std::vector<bool>& components) {
    this->size_ = components.size();

    unsigned int s = this->size_;
    unsigned int c = this->chunk_size_;
    unsigned int i = 0;
    unsigned int k = 0;

    while (i < s) {
      this->components_.push_back(0);

      // Compute the number of bits in the current chunk.
      unsigned int b = i + c > s ? s - i : c;

      for (unsigned int j = 0; j < b; j++) {
        this->components_[k] |= components[i + j] << (b - j - 1);
      }

      i += b;
      k += 1;
    }
  }

  /**
   * Get the number of components in this vector.
   *
   * @return The number of components in this vector.
   */
  unsigned int vector::size() const {
    return this->size_;
  }

  /**
   * Get the component at the specified index of this vector.
   *
   * @param index The index of the component to get.
   * @return The component at the index.
   */
  bool vector::get(unsigned int index) const {
    unsigned int s = this->size_;
    unsigned int c = this->chunk_size_;

    if (index >= s) {
      throw std::out_of_range("Invalid index");
    }

    // Compute the index of the target chunk.
    unsigned int d = index / s;

    // Compute the index of the first bit of the target chunk.
    unsigned int j = d * s;

    // Compute the number of bits in the target chunk.
    unsigned int b = j + c > s ? s - j : c;

    return (this->components_[d] >> (b - (index % s) - 1)) & 1;
  }

  /**
   * Get a string representation of this vector.
   *
   * @return The string representation of the vector.
   */
  std::string vector::to_string() const {
    unsigned int n = this->size_;

    std::string value = "Vector[";

    for (unsigned int i = 0; i < n; i++) {
      value += std::to_string(this->get(i));
    }

    return value + "]";
  }

  /**
   * Check if this vector equals another vector.
   *
   * @param vector The other vector.
   * @return `true` if this vector equals the other vector, otherwise `false`.
   */
  bool vector::operator==(const vector& vector) const {
    if (this->size() != vector.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    return vector::distance(*this, vector) == 0;
  }

  /**
   * Compute the dot product of this and another vector.
   *
   * @param vector The other vector.
   * @return The dot product of this and another vector.
   */
  unsigned int vector::operator*(const vector& vector) const {
    if (this->size() != vector.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    unsigned int d = 0;
    unsigned int n = this->components_.size();

    for (unsigned int i = 0; i < n; i++) {
      d += __builtin_popcount(this->components_[i] & vector.components_[i]);
    }

    return d;
  }

  /**
   * Compute the dot product of this vector and an integer.
   *
   * @param integer The integer.
   * @return The dot product of this vector and an integer.
   */
  unsigned int vector::operator*(unsigned int integer) const {
    unsigned int d = 0;
    unsigned int s = this->size_;
    unsigned int c = this->chunk_size_;
    unsigned int n = this->components_.size();

    for (unsigned int i = 0; i < n; i++) {
      // Compute the index of the first bit of the current chunk.
      unsigned int j = c * i;

      // Compute the number of bits in the current chunk.
      unsigned int m = j + c > s ? s - j : c;

      // Grab the bits of the integer that correspond to the current chunk.
      unsigned int b = (integer >> (s - j - m)) % (1 << m);

      d += __builtin_popcount(this->components_[i] & b);
    }

    return d;
  }

  /**
   * Compute the bitwise AND of this and another vector.
   *
   * @param vector The other vector.
   * @return The bitwise AND of this and another vector.
   */
  vector vector::operator&(const vector& vector) const {
    if (this->size() != vector.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    std::vector<unsigned int> c;

    unsigned int n = this->components_.size();

    for (unsigned int i = 0; i < n; i++) {
      c.push_back(this->components_[i] & vector.components_[i]);
    }

    return lsh::vector(c, this->size_);
  }

  /**
   * Compupte the hash of this vector.
   *
   * @return The hash of this vector.
   */
  int vector::hash() const {
    unsigned int n = this->components_.size();
    unsigned long h = 7;

    for (unsigned int i = 0; i < n; i++) {
      h = 31 * h + this->components_[i];
    }

    return h ^ (h >> 32);
  }

  /**
   * Compute the distance between two vectors.
   *
   * @see http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
   *
   * @param u The first vector.
   * @param v The second vector.
   * @return The distance between the two vectors.
   */
  int vector::distance(const vector& u, const vector& v) {
    if (u.size() != v.size()) {
      throw std::invalid_argument("Invalid vector size");
    }

    unsigned int d = 0;
    unsigned int n = u.components_.size();

    for (unsigned int i = 0; i < n; i++) {
      unsigned int x = u.components_[i] ^ v.components_[i];

      while (x) {
        x &= x - 1;
        d++;
      }
    }

    return d;
  }

  /**
   * Construct a random vector of a given dimensionality.
   *
   * @param dimensions The number of dimensions in the vector.
   * @return The randomly generated vector.
   */
  vector vector::random(unsigned int dimensions) {
    std::random_device random;
    std::mt19937 generator(random());
    std::uniform_int_distribution<> components(0, 1);

    std::vector<bool> c;

    for (unsigned int i = 0; i < dimensions; i++) {
      c.push_back(components(generator));
    }

    return vector(c);
  }
}
<|endoftext|>


<commit_before>// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/version.h"

// These macros define the version number for the current version.
// NOTE these macros are used by some of the tool scripts and the build
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION     3
#define MINOR_VERSION     28
#define BUILD_NUMBER      27
#define PATCH_LEVEL       0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 1

// Define SONAME to have the build system put a specific SONAME into the
// shared library instead the generic SONAME generated from the V8 version
// number. This define is mainly used by the build system script.
#define SONAME            ""

#if IS_CANDIDATE_VERSION
#define CANDIDATE_STRING " (candidate)"
#else
#define CANDIDATE_STRING ""
#endif

#define SX(x) #x
#define S(x) SX(x)

#if PATCH_LEVEL > 0
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER) "."              \
        S(PATCH_LEVEL) CANDIDATE_STRING
#else
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER)                  \
        CANDIDATE_STRING
#endif

namespace v8 {
namespace internal {

int Version::major_ = MAJOR_VERSION;
int Version::minor_ = MINOR_VERSION;
int Version::build_ = BUILD_NUMBER;
int Version::patch_ = PATCH_LEVEL;
bool Version::candidate_ = (IS_CANDIDATE_VERSION != 0);
const char* Version::soname_ = SONAME;
const char* Version::version_string_ = VERSION_STRING;

// Calculate the V8 version string.
void Version::GetString(Vector<char> str) {
  const char* candidate = IsCandidate() ? " (candidate)" : "";
#ifdef USE_SIMULATOR
  const char* is_simulator = " SIMULATOR";
#else
  const char* is_simulator = "";
#endif  // USE_SIMULATOR
  if (GetPatch() > 0) {
    SNPrintF(str, "%d.%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate,
             is_simulator);
  } else {
    SNPrintF(str, "%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), candidate,
             is_simulator);
  }
}

// Calculate the SONAME for the V8 shared library.
void Version::GetSONAME(Vector<char> str) {
  if (soname_ == NULL || *soname_ == '\0') {
    // Generate generic SONAME if no specific SONAME is defined.
    const char* candidate = IsCandidate() ? "-candidate" : "";
    if (GetPatch() > 0) {
      SNPrintF(str, "libv8-%d.%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate);
    } else {
      SNPrintF(str, "libv8-%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), candidate);
    }
  } else {
    // Use specific SONAME.
    SNPrintF(str, "%s", soname_);
  }
}

} }  // namespace v8::internal
<commit_msg>[Auto-roll] Bump up version to 3.28.29.0<commit_after>// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/version.h"

// These macros define the version number for the current version.
// NOTE these macros are used by some of the tool scripts and the build
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION     3
#define MINOR_VERSION     28
#define BUILD_NUMBER      29
#define PATCH_LEVEL       0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 1

// Define SONAME to have the build system put a specific SONAME into the
// shared library instead the generic SONAME generated from the V8 version
// number. This define is mainly used by the build system script.
#define SONAME            ""

#if IS_CANDIDATE_VERSION
#define CANDIDATE_STRING " (candidate)"
#else
#define CANDIDATE_STRING ""
#endif

#define SX(x) #x
#define S(x) SX(x)

#if PATCH_LEVEL > 0
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER) "."              \
        S(PATCH_LEVEL) CANDIDATE_STRING
#else
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER)                  \
        CANDIDATE_STRING
#endif

namespace v8 {
namespace internal {

int Version::major_ = MAJOR_VERSION;
int Version::minor_ = MINOR_VERSION;
int Version::build_ = BUILD_NUMBER;
int Version::patch_ = PATCH_LEVEL;
bool Version::candidate_ = (IS_CANDIDATE_VERSION != 0);
const char* Version::soname_ = SONAME;
const char* Version::version_string_ = VERSION_STRING;

// Calculate the V8 version string.
void Version::GetString(Vector<char> str) {
  const char* candidate = IsCandidate() ? " (candidate)" : "";
#ifdef USE_SIMULATOR
  const char* is_simulator = " SIMULATOR";
#else
  const char* is_simulator = "";
#endif  // USE_SIMULATOR
  if (GetPatch() > 0) {
    SNPrintF(str, "%d.%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate,
             is_simulator);
  } else {
    SNPrintF(str, "%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), candidate,
             is_simulator);
  }
}

// Calculate the SONAME for the V8 shared library.
void Version::GetSONAME(Vector<char> str) {
  if (soname_ == NULL || *soname_ == '\0') {
    // Generate generic SONAME if no specific SONAME is defined.
    const char* candidate = IsCandidate() ? "-candidate" : "";
    if (GetPatch() > 0) {
      SNPrintF(str, "libv8-%d.%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate);
    } else {
      SNPrintF(str, "libv8-%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), candidate);
    }
  } else {
    // Use specific SONAME.
    SNPrintF(str, "%s", soname_);
  }
}

} }  // namespace v8::internal
<|endoftext|>


<commit_before>/******************************************************************************
* Turbo C++11 metaprogramming Library                                         *
*                                                                             *
* Copyright (C) 2013 - 2014, Manuel Sánchez Pérez                             *
*                                                                             *
* This file is part of The Turbo Library.                                     *
*                                                                             *
* The Turbo Library 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, version 2 of the License.                     *
*                                                                             *
* The Turbo Library is distributed in the hope that it will be useful,        *
* but WITHOUT ANY WARRANTY; without even the implied warranty of              *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
* GNU Lesser General Public License for more details.                         *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with The Turbo Library. If not, see <http://www.gnu.org/licenses/>.   *
******************************************************************************/

#ifndef LAZY_HPP
#define	LAZY_HPP

#include "eval.hpp"

namespace tml
{
    /*
     * Wraps a template to provide lazy template instantation
     *
     *
     * There are situations where a template will be evaluated/instantiated later, but the
     * use of placeholders is not possible due to the way they are used inside the template. For example:
     *
     *     template<typename V>
     *     using increment = std::integral_constant<int,V::value + 1>;
     *
     *     using result = tml::map<increment<_1>,tml::integer_list<1,2,3,4,5>>; //ERROR: tml::placeholders::_1 has no member "value"
     *
     * The template tml::lazy is dessigned to wrap a template in a type (Instead of a template parameter), and instantiate
     * it later with a set of parameters.
     * This allows the user to pass templates through metafunctions without instantiating them, making the use of placeholders not
     * necessary. Also lazy template instantation could be used to leave complex template instantations (Instantations which could take a long
     * time/effort) until the point of its ussage.
     */
    template<template<typename...> class F>
    struct lazy
    {
        template<typename... ARGS>
        using instance = F<ARGS...>;
    };

    /*
     * Instantiates a template wrapped by L using the specified template argumments.
     */
    template<typename L , typename... ARGS>
    using lazy_instance = typename L::template instance<ARGS...>;

    /*
     * tml::eval is overrided to take care of wrapped templates. A wrapped template should be evaluated with a set of parameters.
     * That parameters are used to instantiate the template and evaluate the resulting instance later.
     */

    template<template<typename...> class F>
    struct overrides_eval<tml::lazy<F>> : public tml::true_type
    {};

    namespace impl
    {
        template<template<typename...> class F , typename ARG , typename... ARGS>
        struct eval<tml::lazy<F>,tml::list<ARG,ARGS...>> :
        public tml::function<tml::eval<tml::lazy_instance<tml::lazy<F>,ARG,ARGS...>>>
        {};
    }
}

#endif	/* LAZY_HPP */

<commit_msg>Delayed conditionañ<commit_after>/******************************************************************************
* Turbo C++11 metaprogramming Library                                         *
*                                                                             *
* Copyright (C) 2013 - 2014, Manuel Sánchez Pérez                             *
*                                                                             *
* This file is part of The Turbo Library.                                     *
*                                                                             *
* The Turbo Library 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, version 2 of the License.                     *
*                                                                             *
* The Turbo Library is distributed in the hope that it will be useful,        *
* but WITHOUT ANY WARRANTY; without even the implied warranty of              *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
* GNU Lesser General Public License for more details.                         *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with The Turbo Library. If not, see <http://www.gnu.org/licenses/>.   *
******************************************************************************/

#ifndef LAZY_HPP
#define	LAZY_HPP

#include "eval.hpp"

namespace tml
{
    /*
     * Wraps a template to provide lazy template instantation
     *
     *
     * There are situations where a template will be evaluated/instantiated later, but the
     * use of placeholders is not possible due to the way they are used inside the template. For example:
     *
     *     template<typename V>
     *     using increment = std::integral_constant<int,V::value + 1>;
     *
     *     using result = tml::map<increment<_1>,tml::integer_list<1,2,3,4,5>>; //ERROR: tml::placeholders::_1 has no member "value"
     *
     * The template tml::lazy is dessigned to wrap a template in a type (Instead of a template parameter), and instantiate
     * it later with a set of parameters.
     * This allows the user to pass templates through metafunctions without instantiating them, making the use of placeholders not
     * necessary. Also lazy template instantation could be used to leave complex template instantations (Instantations which could take a long
     * time/effort) until the point of its ussage.
     */
    template<template<typename...> class F>
    struct lazy
    {
        template<typename... ARGS>
        using instance = F<ARGS...>;
    };

    /*
     * Instantiates a template wrapped by L using the specified template argumments.
     */
    template<typename L , typename... ARGS>
    using lazy_instance = typename L::template instance<ARGS...>;

    /*
     * tml::eval is overrided to take care of wrapped templates. A wrapped template should be evaluated with a set of parameters.
     * That parameters are used to instantiate the template and evaluate the resulting instance later.
     */

    template<template<typename...> class F>
    struct overrides_eval<tml::lazy<F>> : public tml::true_type
    {};

    namespace impl
    {
        template<template<typename...> class F , typename ARG , typename... ARGS>
        struct eval<tml::lazy<F>,tml::list<ARG,ARGS...>> :
            public tml::function<tml::eval<tml::lazy_instance<tml::lazy<F>,ARG,ARGS...>>>
        {};
    }
}

#endif	/* LAZY_HPP */

<|endoftext|>


<commit_before>#include "service.hpp"

#include "../libkhax/khax.h"

#include <malloc.h>
#include <stdio.h>

#include <functional>
#include <map>

#include <3ds.h>

#define GET_BITS(v, s, e) (((v) >> (s)) & ((1 << ((e) - (s) + 1)) - 1))

static u32* socBuffer;

Result socInit() {
    socBuffer = (u32*) memalign(0x1000, 0x100000);
    if(socBuffer == NULL) {
        return -1;
    }

    Result socResult = SOC_Initialize(socBuffer, 0x100000);
    if(socResult != 0) {
        free(socBuffer);
        socBuffer = NULL;
        return socResult;
    }

    return 0;
}

void socCleanup() {
    SOC_Shutdown();
    if(socBuffer != NULL) {
        free(socBuffer);
        socBuffer = NULL;
    }
}

static std::map<std::string, std::function<void()>> services;

void serviceCleanup() {
    for(std::map<std::string, std::function<void()>>::iterator it = services.begin(); it != services.end(); it++) {
        if((*it).second != NULL) {
            (*it).second();
        }
    }

    services.clear();
}

bool serviceRequire(const std::string service) {
    if(services.find(service) != services.end()) {
        return true;
    }

    Result result = 0;
    std::function<void()> cleanup = NULL;
    if(service.compare("gfx") == 0) {
        result = (gfxInitDefault(), 0);
        cleanup = &gfxExit;
    } else if(service.compare("soc") == 0) {
        result = socInit();
        cleanup = &socCleanup;
    } else if(service.compare("csnd") == 0) {
        result = csndInit();
        cleanup = &csndExit;
    } else if(service.compare("kernel") == 0) {
        result = khaxInit();
        cleanup = &khaxExit;
    } else {
        if(!platformIsNinjhax() || serviceRequire("kernel")) {
            if(service.compare("am") == 0) {
                result = amInit();
                cleanup = &amExit;
            }
        } else {
            return false;
        }
    }

    if(result == 0) {
        services[service] = cleanup;
    } else {
        platformSetError(serviceParseError((u32) result));
    }

    return result == 0;
}

Error serviceParseError(u32 error) {
    Error err;

    u32 module = GET_BITS(error, 10, 17);
    if(module == 79) {
        module = MODULE_RO;
    }

    err.raw = error;
    err.module = (ErrorModule) module;
    err.level = (ErrorLevel) GET_BITS(error, 27, 31);
    err.summary = (ErrorSummary) GET_BITS(error, 21, 26);
    err.description = (ErrorDescription) GET_BITS(error, 0, 9);

    return err;
}<commit_msg>Require kernel for N3DS CSND.<commit_after>#include "service.hpp"

#include "../libkhax/khax.h"

#include <malloc.h>
#include <stdio.h>

#include <functional>
#include <map>

#include <3ds.h>

#define GET_BITS(v, s, e) (((v) >> (s)) & ((1 << ((e) - (s) + 1)) - 1))

static u32* socBuffer;

Result socInit() {
    socBuffer = (u32*) memalign(0x1000, 0x100000);
    if(socBuffer == NULL) {
        return -1;
    }

    Result socResult = SOC_Initialize(socBuffer, 0x100000);
    if(socResult != 0) {
        free(socBuffer);
        socBuffer = NULL;
        return socResult;
    }

    return 0;
}

void socCleanup() {
    SOC_Shutdown();
    if(socBuffer != NULL) {
        free(socBuffer);
        socBuffer = NULL;
    }
}

static std::map<std::string, std::function<void()>> services;

void serviceCleanup() {
    for(std::map<std::string, std::function<void()>>::iterator it = services.begin(); it != services.end(); it++) {
        if((*it).second != NULL) {
            (*it).second();
        }
    }

    services.clear();
}

bool serviceRequire(const std::string service) {
    if(services.find(service) != services.end()) {
        return true;
    }

    Result result = 0;
    std::function<void()> cleanup = NULL;
    if(service.compare("gfx") == 0) {
        result = (gfxInitDefault(), 0);
        cleanup = &gfxExit;
    } else if(service.compare("soc") == 0) {
        result = socInit();
        cleanup = &socCleanup;
    } else if(service.compare("kernel") == 0) {
        result = khaxInit();
        cleanup = &khaxExit;
    } else {
        bool new3ds = false;
        if(osGetKernelVersion() >= SYSTEM_VERSION(2, 44, 6)) {
            u8 isNew3DS = 0;
            result = APT_CheckNew3DS(NULL, &isNew3DS);
            if(result == 0) {
                new3ds = isNew3DS != 0;
            }
        }

        if(!platformIsNinjhax() || (service.compare("csnd") == 0 && !new3ds) || serviceRequire("kernel")) {
            if(service.compare("am") == 0) {
                result = amInit();
                cleanup = &amExit;
            } else if(service.compare("csnd") == 0) {
                result = csndInit();
                cleanup = &csndExit;
            }
        } else {
            return false;
        }
    }

    if(result == 0) {
        services[service] = cleanup;
    } else {
        platformSetError(serviceParseError((u32) result));
    }

    return result == 0;
}

Error serviceParseError(u32 error) {
    Error err;

    u32 module = GET_BITS(error, 10, 17);
    if(module == 79) {
        module = MODULE_RO;
    }

    err.raw = error;
    err.module = (ErrorModule) module;
    err.level = (ErrorLevel) GET_BITS(error, 27, 31);
    err.summary = (ErrorSummary) GET_BITS(error, 21, 26);
    err.description = (ErrorDescription) GET_BITS(error, 0, 9);

    return err;
}<|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program 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.

This program 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "type/type.pb.h"
#include <google/protobuf/descriptor.h>

#include <boost/thread.hpp>
#include <functional>
#include <string>
#include <iostream>
#include "utils/init.h"
#include "kraken_zmq.h"
#include "utils/zmq_compat.h"

int main(int, char** argv){
    navitia::init_app();
    Configuration* conf = Configuration::get();

    std::string::size_type posSlash = std::string(argv[0]).find_last_of( "\\/" );
    conf->set_string("application", std::string(argv[0]).substr(posSlash+1));
    char buf[256];
    if(getcwd(buf, sizeof(buf))){
        conf->set_string("path",std::string(buf) + "/");
    }else{
        perror("getcwd");
        return 1;
    }

    std::string conf_file = conf->get_string("path") + conf->get_string("application") + ".ini";
    conf->load_ini(conf_file);
    init_logger(conf_file);

    DataManager<navitia::type::Data> data_manager;

    auto logger = log4cplus::Logger::getInstance("startup");
    boost::thread_group threads;
    // Prepare our context and sockets
    zmq::context_t context(1);
    zmq::socket_t clients(context, ZMQ_ROUTER);
    std::string zmq_socket = conf->get_as<std::string>("GENERAL", "zmq_socket", "ipc:///tmp/default_navitia");
    // Catch startup exceptions; without this, startup errors are on stdout
    try{
        clients.bind(zmq_socket.c_str());
        zmq::socket_t workers(context, ZMQ_DEALER);
        workers.bind("inproc://workers");

        threads.create_thread(navitia::MaintenanceWorker(data_manager));

        int nb_threads = conf->get_as<int>("GENERAL", "nb_threads", 1);
        // Launch pool of worker threads
        for(int thread_nbr = 0; thread_nbr < nb_threads; ++thread_nbr) {
            threads.create_thread(std::bind(&doWork, std::ref(context), std::ref(data_manager)));
        }

        // Connect work threads to client threads via a queue
        do{
            try{
                zmq::device(ZMQ_QUEUE, clients, workers);
            }catch(zmq::error_t){}//lors d'un SIGHUP on restore la queue
        }while(true);
    }catch(zmq::error_t& e){
        LOG4CPLUS_ERROR(logger, "Fail to start: " << e.what());
    }

    return 0;
}

<commit_msg>Take advices: only catch bind() calls and return 1<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program 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.

This program 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "type/type.pb.h"
#include <google/protobuf/descriptor.h>

#include <boost/thread.hpp>
#include <functional>
#include <string>
#include <iostream>
#include "utils/init.h"
#include "kraken_zmq.h"
#include "utils/zmq_compat.h"

int main(int, char** argv){
    navitia::init_app();
    Configuration* conf = Configuration::get();

    std::string::size_type posSlash = std::string(argv[0]).find_last_of( "\\/" );
    conf->set_string("application", std::string(argv[0]).substr(posSlash+1));
    char buf[256];
    if(getcwd(buf, sizeof(buf))){
        conf->set_string("path",std::string(buf) + "/");
    }else{
        perror("getcwd");
        return 1;
    }

    std::string conf_file = conf->get_string("path") + conf->get_string("application") + ".ini";
    conf->load_ini(conf_file);
    init_logger(conf_file);

    DataManager<navitia::type::Data> data_manager;

    auto logger = log4cplus::Logger::getInstance("startup");
    boost::thread_group threads;
    // Prepare our context and sockets
    zmq::context_t context(1);
    zmq::socket_t clients(context, ZMQ_ROUTER);
    std::string zmq_socket = conf->get_as<std::string>("GENERAL", "zmq_socket", "ipc:///tmp/default_navitia");
    zmq::socket_t workers(context, ZMQ_DEALER);
    // Catch startup exceptions; without this, startup errors are on stdout
    try{
        clients.bind(zmq_socket.c_str());
        workers.bind("inproc://workers");
    }catch(zmq::error_t& e){
        LOG4CPLUS_ERROR(logger, "zmq::socket_t::bind() failure: " << e.what());
		return 1;
    }

    threads.create_thread(navitia::MaintenanceWorker(data_manager));

    int nb_threads = conf->get_as<int>("GENERAL", "nb_threads", 1);
    // Launch pool of worker threads
    for(int thread_nbr = 0; thread_nbr < nb_threads; ++thread_nbr) {
        threads.create_thread(std::bind(&doWork, std::ref(context), std::ref(data_manager)));
    }

    // Connect work threads to client threads via a queue
    do{
        try{
            zmq::device(ZMQ_QUEUE, clients, workers);
        }catch(zmq::error_t){}//lors d'un SIGHUP on restore la queue
    }while(true);

    return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

#define MAX_PAIR_NUM 1000

int main() {
  cout << "test";
  cout << "test2";
}
<commit_msg>a third test<commit_after>#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

#define MAX_PAIR_NUM 1000

int main() {
  cout << "test";
  cout << "test2";
  cout << "test3";
}
<|endoftext|>


<commit_before>// $Id$
// ===========================================================================
// Include files
// ===========================================================================
// Ostap
// ===========================================================================
#include "Ostap/Interpolation.h"
// ===========================================================================
/** @file
 *  Implementation file for interpolation functions
 *  @see Ostap::Math::Interpolation
 *  @see LHCbMath/Interpolation.h
 *
 *  @date 2016-07-23
 *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
 *
 *                    $Revision$
 *  Last modification $Date$
 *                 by $author$
 */
// ============================================================================
/*  very simp;e lagrange interpolation
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::lagrange
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  )
{
  return lagrange ( xs.begin () ,
                    xs.end   () ,
                    ys.begin () ,
                    ys.end   () ,
                    x           ,
                    0.0         ,
                    [] ( double x ) { return x ; } ,
                    [] ( double y ) { return y ; } ) ;
}
// ============================================================================
/*  very simple lagrange interpolation
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::lagrange
( const Ostap::Math::Interpolation::DATA& data ,
  const double                            x  )
{
  typedef std::pair<double,double>  PP ;
  return lagrange ( data.begin () ,
                    data.end   () ,
                    data.begin () ,
                    data.end   () ,
                    x             ,
                    0.0           ,
                    [] ( const PP& i ) { return i.first  ; } ,
                    [] ( const PP& i ) { return i.second ; } ) ;
}
// ============================================================================
/*  Simple lagrange interpolation
 *  - it also evaluate the derivative wity respect to y_i
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x  INPUT evaluate the polynomial in this point
 *  @param  it INPUT index of y_i, the derivative shodul be calculated.
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::lagrange2
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  ,
  const unsigned int         iy )
{
  const double r = lagrange ( xs.begin () ,
                              xs.end   () ,
                              ys.begin () ,
                              ys.end   () ,
                              x           ,
                              0.0         ,
                              [] ( double x )  { return x ; } ,
                              [] ( double y )  { return y ; } ) ;
  //
  if  ( ys.size() <= iy || xs.size() <= iy ) { return std::make_pair ( r , 0. ) ; } // RETURN
  //
  double  d = 1 ;
  const unsigned int nx = xs.size() ;
  const double       xi = xs[iy]    ;
  for ( unsigned int jx = 0  ; jx < nx ; ++jx )
  {
    if ( jx == iy ) { continue ; }
    const double xj = xs[jx] ;
    d *= ( x - xj ) / ( xi - xj ) ;
  }
  return std::make_pair (  r, d ) ;
}
// ============================================================================
/*  Simple lagrange interpolation
 *  - it also evaluate the derivative wity respect to y_i
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @param  it INPUT index of y_i, the derivative shodul be calculated.
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::lagrange2
( const Ostap::Math::Interpolation::DATA& data ,
  const double                            x    ,
  const unsigned int                      iy   )
{
  typedef std::pair<double,double>  PP ;
  const double r = lagrange ( data.begin () ,
                              data.end   () ,
                              data.begin () ,
                              data.end   () ,
                              x             ,
                              0.0           ,
                              [] ( const PP&i ) { return i.first  ; } ,
                              [] ( const PP&i ) { return i.second ; } ) ;
  //
  if  ( data.size() <= iy ) { return std::make_pair ( r , 0. ) ; } // RETURN
  //
  double  d = 1 ;
  const unsigned int nx = data.size()    ;
  const double       xi = data[iy].first ;
  for ( unsigned int jx = 0  ; jx < nx ; ++jx )
  {
    if ( jx == iy ) { continue ; }
    const double xj = data[jx].first ;
    d *= ( x - xj ) / ( xi - xj ) ;
  }
  return std::make_pair (  r, d ) ;
}
// ============================================================================
/** very simple Neville's interpolation
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::neville
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  )
{
  return neville ( xs.begin() , xs.end  () ,
                   ys.begin() , ys.end  () ,
                   x          ,
                   [] ( double x ) { return x ; } ,
                   [] ( double y ) { return y ; } ) ;
}
// ============================================================================
/*  very simple Neville interpolation
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::neville
( const Ostap::Math::Interpolation::DATA& data , const double x  )
{
  return neville ( data.begin () ,
                   data.end   () ,
                   data.begin () ,
                   data.end   () ,
                   x             ,
                   [] ( const std::pair<double,double>& i ) { return i.first  ; } ,
                   [] ( const std::pair<double,double>& i ) { return i.second ; } );
}
// ============================================================================
/** very simple Neville's interpolation
 *  -  it evaluates the polynomial and the derivative
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::neville2
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  )
{
  return neville2 ( xs.begin() , xs.end  () ,
                    ys.begin() , ys.end  () ,
                    x          ,
                    [] ( double x ) { return x ; } ,
                    [] ( double y ) { return y ; } ) ;
}
// ============================================================================
/*  very simple Neville interpolation
 *  -  it evaluates the polynomial and the derivative
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::neville2
( const Ostap::Math::Interpolation::DATA& data , const double x  )
{
  return neville2 ( data.begin () ,
                    data.end   () ,
                    data.begin () ,
                    data.end   () ,
                    x             ,
                    [] ( const std::pair<double,double>& i ) { return i.first  ; } ,
                    [] ( const std::pair<double,double>& i ) { return i.second ; } );
}
// ============================================================================

// ============================================================================
//  The END
// ============================================================================

<commit_msg>Tiny fix to avoid Coverity warning<commit_after>// $Id$
// ===========================================================================
// Include files
// ===========================================================================
// Ostap
// ===========================================================================
#include "Ostap/Interpolation.h"
// ===========================================================================
/** @file
 *  Implementation file for interpolation functions
 *  @see Ostap::Math::Interpolation
 *  @see Ostap/Interpolation.h
 *
 *  @date 2016-07-23
 *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
 *
 */
// ============================================================================
/*  very simp;e lagrange interpolation
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::lagrange
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  )
{
  return lagrange ( xs.begin () ,
                    xs.end   () ,
                    ys.begin () ,
                    ys.end   () ,
                    x           ,
                    0.0         ,
                    [] ( double z ) { return z ; } ,
                    [] ( double y ) { return y ; } ) ;
}
// ============================================================================
/*  very simple lagrange interpolation
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::lagrange
( const Ostap::Math::Interpolation::DATA& data ,
  const double                            x  )
{
  typedef std::pair<double,double>  PP ;
  return lagrange ( data.begin () ,
                    data.end   () ,
                    data.begin () ,
                    data.end   () ,
                    x             ,
                    0.0           ,
                    [] ( const PP& i ) { return i.first  ; } ,
                    [] ( const PP& i ) { return i.second ; } ) ;
}
// ============================================================================
/*  Simple lagrange interpolation
 *  - it also evaluate the derivative wity respect to y_i
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x  INPUT evaluate the polynomial in this point
 *  @param  it INPUT index of y_i, the derivative shodul be calculated.
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::lagrange2
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  ,
  const unsigned int         iy )
{
  const double r = lagrange ( xs.begin () ,
                              xs.end   () ,
                              ys.begin () ,
                              ys.end   () ,
                              x           ,
                              0.0         ,
                              [] ( double x )  { return x ; } ,
                              [] ( double y )  { return y ; } ) ;
  //
  if  ( ys.size() <= iy || xs.size() <= iy ) { return std::make_pair ( r , 0. ) ; } // RETURN
  //
  double  d = 1 ;
  const unsigned int nx = xs.size() ;
  const double       xi = xs[iy]    ;
  for ( unsigned int jx = 0  ; jx < nx ; ++jx )
  {
    if ( jx == iy ) { continue ; }
    const double xj = xs[jx] ;
    d *= ( x - xj ) / ( xi - xj ) ;
  }
  return std::make_pair (  r, d ) ;
}
// ============================================================================
/*  Simple lagrange interpolation
 *  - it also evaluate the derivative wity respect to y_i
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @param  it INPUT index of y_i, the derivative shodul be calculated.
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::lagrange2
( const Ostap::Math::Interpolation::DATA& data ,
  const double                            x    ,
  const unsigned int                      iy   )
{
  typedef std::pair<double,double>  PP ;
  const double r = lagrange ( data.begin () ,
                              data.end   () ,
                              data.begin () ,
                              data.end   () ,
                              x             ,
                              0.0           ,
                              [] ( const PP&i ) { return i.first  ; } ,
                              [] ( const PP&i ) { return i.second ; } ) ;
  //
  if  ( data.size() <= iy ) { return std::make_pair ( r , 0. ) ; } // RETURN
  //
  double  d = 1 ;
  const unsigned int nx = data.size()    ;
  const double       xi = data[iy].first ;
  for ( unsigned int jx = 0  ; jx < nx ; ++jx )
  {
    if ( jx == iy ) { continue ; }
    const double xj = data[jx].first ;
    d *= ( x - xj ) / ( xi - xj ) ;
  }
  return std::make_pair (  r, d ) ;
}
// ============================================================================
/** very simple Neville's interpolation
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::neville
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  )
{
  return neville ( xs.begin() , xs.end  () ,
                   ys.begin() , ys.end  () ,
                   x          ,
                   [] ( double z ) { return z ; } ,
                   [] ( double y ) { return y ; } ) ;
}
// ============================================================================
/*  very simple Neville interpolation
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
double Ostap::Math::Interpolation::neville
( const Ostap::Math::Interpolation::DATA& data , const double x  )
{
  return neville ( data.begin () ,
                   data.end   () ,
                   data.begin () ,
                   data.end   () ,
                   x             ,
                   [] ( const std::pair<double,double>& i ) { return i.first  ; } ,
                   [] ( const std::pair<double,double>& i ) { return i.second ; } );
}
// ============================================================================
/** very simple Neville's interpolation
 *  -  it evaluates the polynomial and the derivative
 *  @param  xs INPUT sequence of abscissas
 *  @param  ys INPUT sequence of values
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If ys-vector is shorter than x-vector, it is assumed to be zero padded
 *  - If ys-vector is longer  than x-vector, extra avalues are ignored
 *  - If xs-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::neville2
( const std::vector<double>& xs ,
  const std::vector<double>& ys ,
  const double               x  )
{
  return neville2 ( xs.begin() , xs.end  () ,
                    ys.begin() , ys.end  () ,
                    x          ,
                    [] ( double z ) { return z ; } ,
                    [] ( double y ) { return y ; } ) ;
}
// ============================================================================
/*  very simple Neville interpolation
 *  -  it evaluates the polynomial and the derivative
 *  @param  data INPUT sequence of (x,y)
 *  @param  x      INPUT evaluate the polynomial in this point
 *  @return the value of Largange interpolation polynomial at point x
 *
 *  - If data-vector is empty, polynomial is zero
 *
 *  @warning it could be CPU inefficient
 *  @warning it should *NOT* be applied for very long sequence of points
 *           (e.g. >20) due to bad numerical  stability
 *  @author Vanya BELYAEV  Ivan.Belyaev@itep.ru
 *  @date 2016-07-23
 */
// ============================================================================
std::pair<double,double>
Ostap::Math::Interpolation::neville2
( const Ostap::Math::Interpolation::DATA& data , const double x  )
{
  return neville2 ( data.begin () ,
                    data.end   () ,
                    data.begin () ,
                    data.end   () ,
                    x             ,
                    [] ( const std::pair<double,double>& i ) { return i.first  ; } ,
                    [] ( const std::pair<double,double>& i ) { return i.second ; } );
}
// ============================================================================

// ============================================================================
//  The END
// ============================================================================

<|endoftext|>


<commit_before>#ifndef IOD_JSON_HH_
# define IOD_JSON_HH_

#include <vector>
#include <fstream>
#include <cassert>
#include <tuple>
#include <string>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <map>
#include <boost/lexical_cast.hpp>

#include <iod/sio.hh>
#include <iod/foreach.hh>
#include <iod/symbols.hh>
#include <iod/pow_10.hh>
#include <iod/stringview.hh>

// Json IOD api.

namespace iod
{

  using namespace s;

  // Decode \o from a json string \str.
  template <typename ...T>
  inline void json_decode(sio<T...>& o, const stringview& str);

  // Encode \o into a json string.
  template <typename ...T>
  inline std::string json_encode(const sio<T...>& o);

  // Encode \o into a stream.
  template <typename S, typename ...Tail>
  inline void json_encode(const sio<Tail...>& o, S& stream);

  namespace json_internals
  {

    // Json encoder.
    // =============================================
    template <typename T, typename S>
    inline void json_encode_(const T& t, S& ss)
    {
      ss << t;
    }

    template <typename S>
    inline void json_encode_(const char* t, S& ss)
    {
      ss << '"' << t << '"';
    }

    template <typename S>
    inline void json_encode_(const stringview& s, S& ss)
    {
      ss << '"';
      for (int i = 0; i < s.len; i++)
        ss << s.str[i];
      ss << '"';
    }

    template <typename S>
    inline void json_encode_(const std::string& t, S& ss)
    {
      json_encode_(t.c_str(), ss);
    }

    // Forward declaration.
    template <typename S, typename ...Tail>
    inline void json_encode_(const sio<Tail...>& o, S& ss);

    template <typename T, typename S>
    inline void json_encode_(const std::vector<T>& array, S& ss)
    {
      ss << '[';
      for (const auto& t : array)
      {
        json_encode_(t, ss);
        if (&t != &array.back())
          ss << ',';
      }
      ss << ']';
    }

    template <typename S, typename ...Tail>
    inline void json_encode_(const sio<Tail...>& o, S& ss)
    {
      ss << '{';
      int i = 0;
      foreach(o) | [&] (const auto& m)
      {
        json_encode_(m.attributes().get(_Json_symbol, m.symbol()).name(), ss);
        ss << ':';
        json_encode_(m.value(), ss);
        if (i != o.size() - 1) ss << ',';
        i++;
      };
      ss << '}';
    }

    // Json decoder.
    // =============================================

    template <typename T>
    struct fill_ {
      inline fill_(T& _r) : r(_r) {}
      T& r;
    };

    template <typename T>
    inline fill_<T> fill(T& t) { return fill_<T>(t); }

    struct json_parser
    {
      struct spaces_ {} spaces;

      inline json_parser(std::istringstream& _stream) : str(_stream.str()), pos(0) {}
      inline json_parser(const std::string& _str) : str(_str.c_str(), _str.size()), pos(0) {}
      inline json_parser(const stringview& _str) : str(_str), pos(0) {}

      inline char peak() { return str[pos]; }
      inline char eof() { return pos == str.size(); }
      inline char eat_one() { return pos++; }

      template <typename E>
      inline void format_error(E& err) {}

      template <typename E, typename T1, typename... T>
      inline void format_error(E& err, T1 a, T... args)
      {
        err << a;
        format_error(err, args...);
      }

      template <typename... T>
      inline std::runtime_error json_error(T... message)
      {
        std::stringstream err;

        int w = 20;
        int b = pos > w ? pos - w : 0;
        int e = pos < int(str.size()) - w ? pos + w : int(str.size()) - 1;
        std::string near(str.data() + b, str.data() + e);
        err << std::endl << "Json parse error near " << near << std::endl;
        err << "                      ";
        for (int i = 0; i < pos - b - 1; i++) err << ' ';
        err << "^^^"<< std::endl;
        format_error(err, message...);
        return std::runtime_error(err.str());
      }

      inline json_parser& fill(std::string& t)
      {
        int start = pos;
        int end = pos + 1;

        while (!eof() and str[end] != '"') end++;
        t = std::string(str.data() + start, end - start);
        pos = end;
        return *this;
      }

      inline json_parser& fill(stringview& t)
      {
        int start = pos;
        int end = pos + 1;

        while (!eof() and str[end] != '"') end++;
        t.str = str.data() + start;
        t.len = end - start;
        pos = end;
        return *this;
      }

      template <typename I, int N>
      inline json_parser& fill_int(I& val)
      {
        int sign = 1;
        if (std::is_signed<I>::value and str[pos] == '-') { sign = -1; eat_one(); }
        else if (str[pos] == '+') { eat_one(); }

        int end = pos;

        val = 0;

        const char* s = str.data() + pos;

        for (int i = 0; i < N; i++)
        {
          if (s[i] < '0' or s[i] > '9') break;
          val = val * 10 + (s[i] - '0');
          end++;
        }
        val *= sign;

        if (end == pos) throw json_error("Could not find the expected number.");

        pos = end;
        return *this;
      }

      inline json_parser& fill(float& val)
      {
        int end = pos;
        float res = 0;

        int ent = 0;
        fill_int<int, 10>(ent);

        res = ent;

        if (str[pos] == '.')
        {
          eat_one();
          unsigned int floating = 0;
          int start = pos;
          fill_int<unsigned int, 10>(floating);
          int end = pos;
          res += float(floating) / pow_10(end - start);
        }

        if (str[pos] == 'e')
        {
          eat_one();
          int exp = 0;
          fill_int<int, 10>(exp);
          res *= pow_10(exp);
        }

        val = res;
        return *this;
      }

      inline json_parser& fill(int& val) { return fill_int<int, 10>(val); }
      inline json_parser& fill(unsigned int& val) { return fill_int<unsigned int, 10>(val); }

      template <typename T>
      inline json_parser& fill(T& t)
      {
        int end = pos;
        while(!eof() and str[end] != ',' and str[end] != '}' and str[end] != ']') end++;
        t = boost::lexical_cast<std::remove_reference_t<T>>(str.data() + pos, end - pos);
        pos = end;
        return *this;
      }

      template <typename T>
      inline json_parser& operator>>(fill_<T>&& t)
      {
        return fill(t.r);
      }

      inline json_parser& operator>>(char t)
      {
        if (!eof() and str[pos] == t)
        {
          pos++;
          return *this;
        }
        else
        {
          if (eof())
            throw json_error("Expected ", t, " got eof");
          else
            throw json_error("Expected ", t, " got ", str[pos]);
        }
      }

      inline json_parser& operator>>(const char* t)
      {
        int start = pos;
        int end = pos;
        while (!eof() and (t[end - start] == str[end] or str[end] != '"')) end++;

        if (t[end - start] == '\0')
        {
          pos = end;
          return *this;
        }
        else
          throw json_error("Expected ", t, " got something else.");
      }

      inline json_parser& operator>>(spaces_)
      {
        while (!eof() and std::isspace(str[pos])) pos++;
        return *this;
      }

      int line_cpt, char_cpt;
      const char* cur;
      stringview str;
      int pos;
    };

    inline void iod_attr_from_json(sio<>&, json_parser&)
    {
    }

    template <typename T>
    inline void iod_from_json_(T& t, json_parser& p)
    {
      p >> fill(t);
    }

    inline void iod_from_json_(std::string& t, json_parser& p)
    {
      p >> '"' >> fill(t) >> '"';
    }

    inline void iod_from_json_(stringview& t, json_parser& p)
    {
      p >> '"' >> fill(t) >> '"';
    }

    // Parse a json hashmap ordered the field in the object \o.
    template <typename T, typename ...Tail>
    inline void iod_attr_from_json_strict(sio<T, Tail...>& o, json_parser& p)
    {
      T* attr = &o;

      p >> p.spaces >> '"' >> attr->symbol().name() >> '"' >> p.spaces >> ':';

      iod_from_json_(attr->value(), p);
      if (sizeof...(Tail) != 0)
        p >> p.spaces >> ',';

      iod_attr_from_json(*static_cast<sio<Tail...>*>(&o), p);
    }

    // Parse a json hashmap.
    template <typename T, typename ...Tail>
    inline void iod_attr_from_json(sio<T, Tail...>& o, json_parser& p)
    {
      p >> p.spaces;

      struct attr_info { bool filled; stringview name; };

      attr_info A[std::remove_reference_t<decltype(o)>::size()];

      int i = 0;
      foreach(o) | [&] (auto& m)
      {
        A[i].filled = false;
        stringview name(m.symbol().name(), strlen(m.symbol().name()));
        if (m.attributes().has(_Json_symbol))
        {
          const char* new_name = m.attributes().get(_Json_symbol, _Json_symbol).name();
          name = stringview(new_name, strlen(new_name));
        }
        A[i].name = name;
        i++;
      };

      while (p.peak() != '}')
      {
        stringview attr_name;
        p >> p.spaces >> '"' >> fill(attr_name) >> '"' >> p.spaces >> ':' >> p.spaces;

        int i = 0;
        bool attr_found = false;
        foreach(o) | [&] (auto& m)
        {
          if (!attr_found and attr_name == A[i].name)
          {
            iod_from_json_(m.value(), p);
            A[i].filled = true;
            attr_found = true;
          }
          i++;
        };
        // Fixme: if !attr_found, skip the json value.
        p >> p.spaces;
        if (p.peak() == ',')
          p.eat_one();
        else
          break;
      }

      if (p.peak() != '}')
      {
        throw p.json_error("Expected } got ", p.peak());
      }

      i = 0;
      foreach(o) | [&] (auto& m) {
        typename std::remove_reference_t<decltype(m)>::attributes_type attrs;
        if (!m.attributes().has(_Optional) and !A[i].filled)
          throw std::runtime_error(std::string("json_decode error: missing field ") +
                                   m.symbol().name());
        i++;
      };
    }

    // Parse an array.
    template <typename T>
    inline void iod_from_json_(std::vector<T>& array, json_parser& p)
    {
      p >> '[' >> p.spaces;
      if (p.peak() == ']')
      {
        p >> ']';
        return;
      }

      array.clear();
      while (p.peak() != ']')
      {
        T t;
        iod_from_json_(t, p);
        array.push_back(t);
        p >> p.spaces;
        if (p.peak() == ']')
          break;
        else
          p >> ',';
      }

      p >> ']';
    }

    template <typename ...Tail>
    inline void iod_from_json_(sio<Tail...>& o, json_parser& p)
    {
      p >> p.spaces >> '{';
      iod_attr_from_json(o, p);
      p >> p.spaces >> '}';
    }

    template <typename ...Tail>
    inline void iod_from_json_(sio<Tail...>& o, const std::string& str)
    {
      json_parser p(str);
      if (str.size() > 0)
        iod_from_json_(o, p);
      else
        throw std::runtime_error("Empty string.");
    }
  }

  template <typename ...Tail>
  inline void json_decode(sio<Tail...>& o, const stringview& str, int& n_read)
  {
    json_internals::json_parser p(str);
    if (str.size() > 0)
      iod_from_json_(o, p);
    else
      throw std::runtime_error("Empty string.");
    n_read = p.pos;
  }

  template <typename ...Tail>
  inline void json_decode(sio<Tail...>& o, const stringview& str)
  {
    json_internals::json_parser p(str);
    if (str.size() > 0)
      iod_from_json_(o, p);
    else
      throw std::runtime_error("Empty string.");
  }

  template <typename ...Tail>
  inline void json_decode(sio<Tail...>& o, std::istringstream& stream)
  {
    json_internals::json_parser p(stream);
    if (stream.str().size() > 0)
      iod_from_json_(o, p);
    else
      throw std::runtime_error("Empty string.");
  }

  template <typename ...Tail>
  inline std::string json_encode(const sio<Tail...>& o)
  {
    std::stringstream ss;
    json_internals::json_encode_(o, ss);
    return ss.str();
  }

  template <typename S, typename ...Tail>
  inline void json_encode(const sio<Tail...>& o, S& stream)
  {
    json_internals::json_encode_(o, stream);
  }

}

#endif
<commit_msg>Handle  escaped and uft8 chars.<commit_after>#ifndef IOD_JSON_HH_
# define IOD_JSON_HH_

#include <vector>
#include <fstream>
#include <cassert>
#include <tuple>
#include <string>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <map>
#include <boost/lexical_cast.hpp>

#include <iod/sio.hh>
#include <iod/foreach.hh>
#include <iod/symbols.hh>
#include <iod/pow_10.hh>
#include <iod/stringview.hh>

// Json IOD api.

namespace iod
{

  using namespace s;

  // Decode \o from a json string \str.
  template <typename ...T>
  inline void json_decode(sio<T...>& o, const stringview& str);

  // Encode \o into a json string.
  template <typename ...T>
  inline std::string json_encode(const sio<T...>& o);

  // Encode \o into a stream.
  template <typename S, typename ...Tail>
  inline void json_encode(const sio<Tail...>& o, S& stream);

  namespace json_internals
  {

    // Json encoder.
    // =============================================
    template <typename T, typename S>
    inline void json_encode_(const T& t, S& ss)
    {
      ss << t;
    }

    template <typename S>
    inline void json_encode_(const char* t, S& ss)
    {
      ss << '"' << t << '"';
    }

    template <typename S>
    inline void json_encode_(const stringview& s, S& ss)
    {
      ss << '"';
      for (int i = 0; i < s.len; i++)
        ss << s.str[i];
      ss << '"';
    }

    template <typename S>
    inline void json_encode_(const std::string& t, S& ss)
    {
      json_encode_(t.c_str(), ss);
    }

    // Forward declaration.
    template <typename S, typename ...Tail>
    inline void json_encode_(const sio<Tail...>& o, S& ss);

    template <typename T, typename S>
    inline void json_encode_(const std::vector<T>& array, S& ss)
    {
      ss << '[';
      for (const auto& t : array)
      {
        json_encode_(t, ss);
        if (&t != &array.back())
          ss << ',';
      }
      ss << ']';
    }

    template <typename S, typename ...Tail>
    inline void json_encode_(const sio<Tail...>& o, S& ss)
    {
      ss << '{';
      int i = 0;
      foreach(o) | [&] (const auto& m)
      {
        json_encode_(m.attributes().get(_Json_symbol, m.symbol()).name(), ss);
        ss << ':';
        json_encode_(m.value(), ss);
        if (i != o.size() - 1) ss << ',';
        i++;
      };
      ss << '}';
    }

    // Json decoder.
    // =============================================

    template <typename T>
    struct fill_ {
      inline fill_(T& _r) : r(_r) {}
      T& r;
    };

    template <typename T>
    inline fill_<T> fill(T& t) { return fill_<T>(t); }

    struct json_parser
    {
      struct spaces_ {} spaces;

      inline json_parser(std::istringstream& _stream) : str(_stream.str()), pos(0) {}
      inline json_parser(const std::string& _str) : str(_str.c_str(), _str.size()), pos(0) {}
      inline json_parser(const stringview& _str) : str(_str), pos(0) {}

      inline char peak() { return str[pos]; }
      inline char eof() { return pos == str.size(); }
      inline char eat_one() { return pos++; }

      template <typename E>
      inline void format_error(E& err) {}

      template <typename E, typename T1, typename... T>
      inline void format_error(E& err, T1 a, T... args)
      {
        err << a;
        format_error(err, args...);
      }

      template <typename... T>
      inline std::runtime_error json_error(T... message)
      {
        std::stringstream err;

        int w = 20;
        int b = pos > w ? pos - w : 0;
        int e = pos < int(str.size()) - w ? pos + w : int(str.size()) - 1;
        std::string near(str.data() + b, str.data() + e);
        err << std::endl << "Json parse error near " << near << std::endl;
        err << "                      ";
        for (int i = 0; i < pos - b - 1; i++) err << ' ';
        err << "^^^"<< std::endl;
        format_error(err, message...);
        return std::runtime_error(err.str());
      }

      inline json_parser& fill(std::string& t)
      {
        int start = pos;
        int end = pos;
        t.clear();

        char buffer[128];
        int buffer_pos = 0;
        auto flush = [&] () { t.append(buffer, buffer_pos); buffer_pos = 0; };
        auto append_char = [&] (char c)
        {
          if (buffer_pos == sizeof(buffer)) flush();

          buffer[buffer_pos] = c;
          buffer_pos++;
        };
        auto append_str = [&] (const char* str, int len)
        {
          if (buffer_pos + len > sizeof(buffer)) flush();
          memcpy(buffer + buffer_pos, str, len);
          buffer_pos += len;
        };

        while (true)
        {
          while (!eof() and str[end] != '"' and str[end] != '\\')
            end++;

          if (eof()) throw json_error("Unexpected end of string when parsing a string.");
          append_str(str.data() + start, end - start);

          if (str[end] == '"') break;

          end++;
          switch (str[end])
          {
          case '\'': append_char('\''); break;
          case '"': append_char('"'); break;
          case '\\': append_char('\\'); break;
          case '/': append_char('/'); break;
          case 'n': append_char('\n'); break;
          case 'r': append_char('\r'); break;
          case 't': append_char('\t'); break;
          case 'b': append_char('\b'); break;
          case 'f': append_char('\f'); break;
          case 'v': append_char('\v'); break;
          case '0': append_char('\0'); break;
          case 'u':
            while (true)
            {
              if (str.size() < end + 4)
                throw json_error("Unexpected end of string when decoding an utf8 character");
              end++;

              auto decode_hex_c = [this] (char c) {
                if (c >= '0' and c <= '9') return c - '0';
                else return (10 + c - 'A');
              };

              const char* str2 = str.data() + end;
              char x = (decode_hex_c(str2[0]) << 4) + decode_hex_c(str2[1]);
              if (x) append_char(x);
              append_char((decode_hex_c(str2[2]) << 4) + decode_hex_c(str2[3]));

              end += 4;

              if (str[end] == '\\' and str[end + 1] == 'u')
                end += 1;
              else break;
            }
            break;
          }

          start = end;
        }
        flush();
        pos = end;
        return *this;
      }

      inline json_parser& fill(stringview& t)
      {
        int start = pos;
        int end = pos + 1;

        while (!eof() and str[end] != '"') end++;
        t.str = str.data() + start;
        t.len = end - start;
        pos = end;
        return *this;
      }

      template <typename I, int N>
      inline json_parser& fill_int(I& val)
      {
        int sign = 1;
        if (std::is_signed<I>::value and str[pos] == '-') { sign = -1; eat_one(); }
        else if (str[pos] == '+') { eat_one(); }

        int end = pos;

        val = 0;

        const char* s = str.data() + pos;

        for (int i = 0; i < N; i++)
        {
          if (s[i] < '0' or s[i] > '9') break;
          val = val * 10 + (s[i] - '0');
          end++;
        }
        val *= sign;

        if (end == pos) throw json_error("Could not find the expected number.");

        pos = end;
        return *this;
      }

      inline json_parser& fill(float& val)
      {
        float res = 0;

        int ent = 0;
        fill_int<int, 10>(ent);

        res = ent;

        if (str[pos] == '.')
        {
          eat_one();
          unsigned int floating = 0;
          int start = pos;
          fill_int<unsigned int, 10>(floating);
          int end = pos;
          res += float(floating) / pow_10(end - start);
        }

        if (str[pos] == 'e')
        {
          eat_one();
          int exp = 0;
          fill_int<int, 10>(exp);
          res *= pow_10(exp);
        }

        val = res;
        return *this;
      }

      inline json_parser& fill(int& val) { return fill_int<int, 10>(val); }
      inline json_parser& fill(unsigned int& val) { return fill_int<unsigned int, 10>(val); }

      template <typename T>
      inline json_parser& fill(T& t)
      {
        int end = pos;
        while(!eof() and str[end] != ',' and str[end] != '}' and str[end] != ']') end++;
        t = boost::lexical_cast<std::remove_reference_t<T>>(str.data() + pos, end - pos);
        pos = end;
        return *this;
      }

      template <typename T>
      inline json_parser& operator>>(fill_<T>&& t)
      {
        return fill(t.r);
      }

      inline json_parser& operator>>(char t)
      {
        if (!eof() and str[pos] == t)
        {
          pos++;
          return *this;
        }
        else
        {
          if (eof())
            throw json_error("Expected ", t, " got eof");
          else
            throw json_error("Expected ", t, " got ", str[pos]);
        }
      }

      inline json_parser& operator>>(const char* t)
      {
        int start = pos;
        int end = pos;
        while (!eof() and (t[end - start] == str[end] or str[end] != '"')) end++;

        if (t[end - start] == '\0')
        {
          pos = end;
          return *this;
        }
        else
          throw json_error("Expected ", t, " got something else.");
      }

      inline json_parser& operator>>(spaces_)
      {
        while (!eof() and std::isspace(str[pos])) pos++;
        return *this;
      }

      int line_cpt, char_cpt;
      const char* cur;
      stringview str;
      int pos;
    };

    inline void iod_attr_from_json(sio<>&, json_parser&)
    {
    }

    template <typename T>
    inline void iod_from_json_(T& t, json_parser& p)
    {
      p >> fill(t);
    }

    inline void iod_from_json_(std::string& t, json_parser& p)
    {
      p >> '"' >> fill(t) >> '"';
    }

    inline void iod_from_json_(stringview& t, json_parser& p)
    {
      p >> '"' >> fill(t) >> '"';
    }

    // Parse a json hashmap ordered the field in the object \o.
    template <typename T, typename ...Tail>
    inline void iod_attr_from_json_strict(sio<T, Tail...>& o, json_parser& p)
    {
      T* attr = &o;

      p >> p.spaces >> '"' >> attr->symbol().name() >> '"' >> p.spaces >> ':';

      iod_from_json_(attr->value(), p);
      if (sizeof...(Tail) != 0)
        p >> p.spaces >> ',';

      iod_attr_from_json(*static_cast<sio<Tail...>*>(&o), p);
    }

    // Parse a json hashmap.
    template <typename T, typename ...Tail>
    inline void iod_attr_from_json(sio<T, Tail...>& o, json_parser& p)
    {
      p >> p.spaces;

      struct attr_info { bool filled; stringview name; };

      attr_info A[std::remove_reference_t<decltype(o)>::size()];

      int i = 0;
      foreach(o) | [&] (auto& m)
      {
        A[i].filled = false;
        stringview name(m.symbol().name(), strlen(m.symbol().name()));
        if (m.attributes().has(_Json_symbol))
        {
          const char* new_name = m.attributes().get(_Json_symbol, _Json_symbol).name();
          name = stringview(new_name, strlen(new_name));
        }
        A[i].name = name;
        i++;
      };

      while (p.peak() != '}')
      {
        stringview attr_name;
        p >> p.spaces >> '"' >> fill(attr_name) >> '"' >> p.spaces >> ':' >> p.spaces;

        int i = 0;
        bool attr_found = false;
        foreach(o) | [&] (auto& m)
        {
          if (!attr_found and attr_name == A[i].name)
          {
            iod_from_json_(m.value(), p);
            A[i].filled = true;
            attr_found = true;
          }
          i++;
        };
        // Fixme: if !attr_found, skip the json value.
        p >> p.spaces;
        if (p.peak() == ',')
          p.eat_one();
        else
          break;
      }

      if (p.peak() != '}')
      {
        throw p.json_error("Expected } got ", p.peak());
      }

      i = 0;
      foreach(o) | [&] (auto& m) {
        typename std::remove_reference_t<decltype(m)>::attributes_type attrs;
        if (!m.attributes().has(_Optional) and !A[i].filled)
          throw std::runtime_error(std::string("json_decode error: missing field ") +
                                   m.symbol().name());
        i++;
      };
    }

    // Parse an array.
    template <typename T>
    inline void iod_from_json_(std::vector<T>& array, json_parser& p)
    {
      p >> '[' >> p.spaces;
      if (p.peak() == ']')
      {
        p >> ']';
        return;
      }

      array.clear();
      while (p.peak() != ']')
      {
        T t;
        iod_from_json_(t, p);
        array.push_back(t);
        p >> p.spaces;
        if (p.peak() == ']')
          break;
        else
          p >> ',';
      }

      p >> ']';
    }

    template <typename ...Tail>
    inline void iod_from_json_(sio<Tail...>& o, json_parser& p)
    {
      p >> p.spaces >> '{';
      iod_attr_from_json(o, p);
      p >> p.spaces >> '}';
    }

    template <typename ...Tail>
    inline void iod_from_json_(sio<Tail...>& o, const std::string& str)
    {
      json_parser p(str);
      if (str.size() > 0)
        iod_from_json_(o, p);
      else
        throw std::runtime_error("Empty string.");
    }
  }

  template <typename ...Tail>
  inline void json_decode(sio<Tail...>& o, const stringview& str, int& n_read)
  {
    json_internals::json_parser p(str);
    if (str.size() > 0)
      iod_from_json_(o, p);
    else
      throw std::runtime_error("Empty string.");
    n_read = p.pos;
  }

  template <typename ...Tail>
  inline void json_decode(sio<Tail...>& o, const stringview& str)
  {
    json_internals::json_parser p(str);
    if (str.size() > 0)
      iod_from_json_(o, p);
    else
      throw std::runtime_error("Empty string.");
  }

  template <typename ...Tail>
  inline void json_decode(sio<Tail...>& o, std::istringstream& stream)
  {
    json_internals::json_parser p(stream);
    if (stream.str().size() > 0)
      iod_from_json_(o, p);
    else
      throw std::runtime_error("Empty string.");
  }

  template <typename ...Tail>
  inline std::string json_encode(const sio<Tail...>& o)
  {
    std::stringstream ss;
    json_internals::json_encode_(o, ss);
    return ss.str();
  }

  template <typename S, typename ...Tail>
  inline void json_encode(const sio<Tail...>& o, S& stream)
  {
    json_internals::json_encode_(o, stream);
  }

}

#endif
<|endoftext|>