<commit_before>#pragma once
#ifndef LIGHTPTR_HPP
# define LIGHTPTR_HPP

#include <cassert>

#include <atomic>

#include <memory>

#include <utility>

#include <type_traits>

namespace detail
{
  using counter_type = ::std::size_t;

  using atomic_type = ::std::atomic<counter_type>;

  using deleter_type = void (*)(void*);

  template <typename U>
  struct ref_type
  {
    using type = U&;
  };

  template <>
  struct ref_type<void>
  {
    using type = void;
  };

  inline void dec_ref(atomic_type* const counter_ptr,
    void* const ptr, deleter_type const deleter)
  {
    if (counter_ptr && (counter_type(1) ==
      counter_ptr->fetch_sub(counter_type(1), ::std::memory_order_relaxed)))
    {
      delete counter_ptr;

      deleter(ptr);
    }
    // else do nothing
  }

  inline void inc_ref(atomic_type* const counter_ptr)
  {
    assert(counter_ptr);
    counter_ptr->fetch_add(counter_type(1), ::std::memory_order_relaxed);
  }
}

template <typename T>
struct light_ptr
{
  template <typename U>
  struct deletion_type
  {
    using type = U;
  };

  template <typename U>
  struct deletion_type<U[]>
  {
    using type = U[];
  };

  template <typename U, ::std::size_t N>
  struct deletion_type<U[N]>
  {
    using type = U[];
  };

  template <typename U>
  struct remove_array
  {
    using type = U;
  };

  template <typename U>
  struct remove_array<U[]>
  {
    using type = U;
  };

  template <typename U, ::std::size_t N>
  struct remove_array<U[N]>
  {
    using type = U;
  };

  using counter_type = ::detail::counter_type;

  using deleter_type = ::detail::deleter_type;

  using element_type = typename remove_array<T>::type;

  light_ptr() = default;

  explicit light_ptr(element_type* const p,
    deleter_type const d = default_deleter)
  {
    reset(p, d);
  }

  ~light_ptr() { ::detail::dec_ref(counter_ptr_, ptr_, deleter_); }

  light_ptr(light_ptr const& other) { *this = other; }

  light_ptr(light_ptr&& other) noexcept { *this = ::std::move(other); }

  light_ptr& operator=(light_ptr const& rhs)
  {
    if (*this != rhs)
    {
      ::detail::dec_ref(counter_ptr_, ptr_, deleter_);

      counter_ptr_ = rhs.counter_ptr_;
      ptr_ = rhs.ptr_;

      deleter_ = rhs.deleter_;

      ::detail::inc_ref(counter_ptr_);
    }
    // else do nothing

    return *this;
  }

  light_ptr& operator=(light_ptr&& rhs) noexcept
  {
    if (*this != rhs)
    {
      counter_ptr_ = rhs.counter_ptr_;
      ptr_ = rhs.ptr_;

      deleter_ = rhs.deleter_;

      rhs.counter_ptr_ = nullptr;
      rhs.ptr_ = nullptr;
    }
    // else do nothing

    return *this;
  }

  bool operator<(light_ptr const& rhs) const noexcept
  {
    return get() < rhs.get();
  }

  bool operator==(light_ptr const& rhs) const noexcept
  {
    return counter_ptr_ == rhs.counter_ptr_;
  }

  bool operator!=(light_ptr const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return !operator==(nullptr);
  }

  explicit operator bool() const noexcept { return ptr_; }

  typename ::detail::ref_type<T>::type
  operator*() const noexcept
  {
    return *static_cast<T*>(static_cast<void*>(ptr_));
  }

  T* operator->() const noexcept
  {
    return static_cast<T*>(static_cast<void*>(ptr_));
  }

  element_type* get() const noexcept { return ptr_; }

  void reset() { reset(nullptr); }

  void reset(::std::nullptr_t const)
  {
    ::detail::dec_ref(counter_ptr_, ptr_, deleter_);

    counter_ptr_ = nullptr;
    ptr_ = nullptr;
  }

  void reset(element_type* const p,
    deleter_type const d = default_deleter)
  {
    ::detail::dec_ref(counter_ptr_, ptr_, deleter_);

    counter_ptr_ = new ::detail::atomic_type(counter_type(1));
    ptr_ = p;

    deleter_ = d;
  }

  void swap(light_ptr& other) noexcept
  {
    ::std::swap(counter_ptr_, other.counter_ptr_);
    ::std::swap(ptr_, other.ptr_);
    ::std::swap(deleter_, other.deleter_);
  }

  bool unique() const noexcept { return counter_type(1) == use_count(); }

  counter_type use_count() const noexcept
  {
    return counter_ptr_ ?
      counter_ptr_->load(::std::memory_order_relaxed) :
      counter_type{};
  }

private:
  static void default_deleter(void* const p)
  {
    ::std::default_delete<typename deletion_type<T>::type>()(
      static_cast<element_type*>(p));
  }

private:
  ::detail::atomic_type* counter_ptr_{};

  element_type* ptr_{};

  deleter_type deleter_;
};

template<class T, class ...Args>
inline light_ptr<T> make_light(Args&& ...args)
{
  return light_ptr<T>(new T(::std::forward<Args>(args)...));
}

namespace std
{
  template <typename T>
  struct hash<light_ptr<T> >
  {
    size_t operator()(light_ptr<T> const& l) const noexcept
    {
      return hash<typename light_ptr<T>::element_type*>(l.get());
    }
  };
}

#endif // LIGHTPTR_HPP
<commit_msg>some fixes<commit_after>#pragma once
#ifndef LIGHTPTR_HPP
# define LIGHTPTR_HPP

#include <cassert>

#include <atomic>

#include <memory>

#include <utility>

#include <type_traits>

namespace detail
{
  using counter_type = ::std::size_t;

  using atomic_type = ::std::atomic<counter_type>;

  using deleter_type = void (*)(void*);

  template <typename U>
  struct ref_type
  {
    using type = U&;
  };

  template <>
  struct ref_type<void>
  {
    using type = void;
  };

  inline void dec_ref(atomic_type* const counter_ptr,
    void* const ptr, deleter_type const deleter)
  {
    if (counter_ptr && (counter_type(1) ==
      counter_ptr->fetch_sub(counter_type(1), ::std::memory_order_relaxed)))
    {
      delete counter_ptr;

      deleter(ptr);
    }
    // else do nothing
  }

  inline void inc_ref(atomic_type* const counter_ptr)
  {
    assert(counter_ptr);
    counter_ptr->fetch_add(counter_type(1), ::std::memory_order_relaxed);
  }
}

template <typename T>
struct light_ptr
{
  template <typename U>
  struct deletion_type
  {
    using type = U;
  };

  template <typename U>
  struct deletion_type<U[]>
  {
    using type = U[];
  };

  template <typename U, ::std::size_t N>
  struct deletion_type<U[N]>
  {
    using type = U[];
  };

  template <typename U>
  struct remove_array
  {
    using type = U;
  };

  template <typename U>
  struct remove_array<U[]>
  {
    using type = U;
  };

  template <typename U, ::std::size_t N>
  struct remove_array<U[N]>
  {
    using type = U;
  };

  using counter_type = ::detail::counter_type;

  using deleter_type = ::detail::deleter_type;

  using element_type = typename remove_array<T>::type;

  light_ptr() = default;

  explicit light_ptr(element_type* const p,
    deleter_type const d = default_deleter)
  {
    reset(p, d);
  }

  ~light_ptr() { ::detail::dec_ref(counter_ptr_, ptr_, deleter_); }

  light_ptr(light_ptr const& other) { *this = other; }

  light_ptr(light_ptr&& other) noexcept { *this = ::std::move(other); }

  light_ptr& operator=(light_ptr const& rhs)
  {
    if (*this != rhs)
    {
      ::detail::dec_ref(counter_ptr_, ptr_, deleter_);

      counter_ptr_ = rhs.counter_ptr_;
      ptr_ = rhs.ptr_;

      deleter_ = rhs.deleter_;

      ::detail::inc_ref(counter_ptr_);
    }
    // else do nothing

    return *this;
  }

  light_ptr& operator=(light_ptr&& rhs) noexcept
  {
    if (*this != rhs)
    {
      counter_ptr_ = rhs.counter_ptr_;
      ptr_ = rhs.ptr_;

      deleter_ = rhs.deleter_;

      rhs.counter_ptr_ = nullptr;
      rhs.ptr_ = nullptr;
    }
    // else do nothing

    return *this;
  }

  bool operator<(light_ptr const& rhs) const noexcept
  {
    return get() < rhs.get();
  }

  bool operator==(light_ptr const& rhs) const noexcept
  {
    return counter_ptr_ == rhs.counter_ptr_;
  }

  bool operator!=(light_ptr const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return !ptr_;
  }

  explicit operator bool() const noexcept { return ptr_; }

  typename ::detail::ref_type<T>::type
  operator*() const noexcept
  {
    return *static_cast<T*>(static_cast<void*>(ptr_));
  }

  T* operator->() const noexcept
  {
    return static_cast<T*>(static_cast<void*>(ptr_));
  }

  element_type* get() const noexcept { return ptr_; }

  void reset() { reset(nullptr); }

  void reset(::std::nullptr_t const)
  {
    ::detail::dec_ref(counter_ptr_, ptr_, deleter_);

    counter_ptr_ = nullptr;
    ptr_ = nullptr;
  }

  void reset(element_type* const p,
    deleter_type const d = default_deleter)
  {
    ::detail::dec_ref(counter_ptr_, ptr_, deleter_);

    counter_ptr_ = new ::detail::atomic_type(counter_type(1));
    ptr_ = p;

    deleter_ = d;
  }

  void swap(light_ptr& other) noexcept
  {
    ::std::swap(counter_ptr_, other.counter_ptr_);
    ::std::swap(ptr_, other.ptr_);
    ::std::swap(deleter_, other.deleter_);
  }

  bool unique() const noexcept { return counter_type(1) == use_count(); }

  counter_type use_count() const noexcept
  {
    return counter_ptr_ ?
      counter_ptr_->load(::std::memory_order_relaxed) :
      counter_type{};
  }

private:
  static void default_deleter(void* const p)
  {
    ::std::default_delete<typename deletion_type<T>::type>()(
      static_cast<element_type*>(p));
  }

private:
  ::detail::atomic_type* counter_ptr_{};

  element_type* ptr_{};

  deleter_type deleter_;
};

template<class T, class ...Args>
inline light_ptr<T> make_light(Args&& ...args)
{
  return light_ptr<T>(new T(::std::forward<Args>(args)...));
}

namespace std
{
  template <typename T>
  struct hash<light_ptr<T> >
  {
    size_t operator()(light_ptr<T> const& l) const noexcept
    {
      return hash<typename light_ptr<T>::element_type*>(l.get());
    }
  };
}

#endif // LIGHTPTR_HPP
<|endoftext|>


<commit_before>extern "C" {
#include "nyara.h"
}
#include <ruby/re.h>
#include <ruby/encoding.h>
#include <vector>
#include <map>
#include "inc/str_intern.h"

struct RouteEntry {
  // note on order: scope is supposed to be the last, but when searching, is_sub is checked first
  bool is_sub; // = last_prefix.start_with? prefix
  char* prefix;
  long prefix_len;
  regex_t *suffix_re;
  VALUE controller;
  VALUE id; // symbol
  VALUE accept_exts;  // {ext => true}
  VALUE accept_mimes; // [[m1, m2, ext]]
  std::vector<ID> conv;
  VALUE scope;
  char* suffix; // only for inspect
  long suffix_len;

  // don't make it destructor, or it could be called twice if on stack
  void dealloc() {
    if (prefix) {
      xfree(prefix);
      prefix = NULL;
    }
    if (suffix_re) {
      onig_free(suffix_re);
      suffix_re = NULL;
    }
    if (suffix) {
      xfree(suffix);
      suffix = NULL;
    }
  }
};

typedef std::vector<RouteEntry> RouteEntries;
static std::map<enum http_method, RouteEntries*> route_map;
static OnigRegion region; // we can reuse the region without worrying thread safety
static ID id_to_s;
static rb_encoding* u8_enc;
static VALUE str_html;
static VALUE nyara_http_methods;

static bool start_with(const char* a, long a_len, const char* b, long b_len) {
  if (b_len > a_len) {
    return false;
  }
  for (size_t i = 0; i < b_len; i++) {
    if (a[i] != b[i]) {
      return false;
    }
  }
  return true;
}

static enum http_method canonicalize_http_method(VALUE m) {
  VALUE method_num;
  if (TYPE(m) == T_STRING) {
    method_num = rb_hash_aref(nyara_http_methods, m);
  } else {
    method_num = m;
  }
  Check_Type(method_num, T_FIXNUM);
  return (enum http_method)FIX2INT(method_num);
}

static VALUE ext_clear_route(VALUE req) {
  for (auto i = route_map.begin(); i != route_map.end(); ++i) {
    RouteEntries* entries = i->second;
    for (auto j = entries->begin(); j != entries->end(); ++j) {
      j->dealloc();
    }
    delete entries;
  }
  route_map.clear();
  return Qnil;
}

static VALUE ext_register_route(VALUE self, VALUE v_e) {
  // get route entries
  enum http_method m = canonicalize_http_method(rb_iv_get(v_e, "@http_method"));
  RouteEntries* route_entries;
  auto map_iter = route_map.find(m);
  if (map_iter == route_map.end()) {
    route_entries = new RouteEntries();
    route_map[m] = route_entries;
  } else {
    route_entries = map_iter->second;
  }

  // prefix
  VALUE v_prefix = rb_iv_get(v_e, "@prefix");
  long prefix_len = RSTRING_LEN(v_prefix);
  char* prefix = ALLOC_N(char, prefix_len);
  memcpy(prefix, RSTRING_PTR(v_prefix), prefix_len);

  // check if prefix is substring of last entry
  bool is_sub = false;
  if (route_entries->size()) {
    is_sub = start_with(route_entries->rbegin()->prefix, route_entries->rbegin()->prefix_len, prefix, prefix_len);
  }

  // suffix
  VALUE v_suffix = rb_iv_get(v_e, "@suffix");
  long suffix_len = RSTRING_LEN(v_suffix);
  char* suffix = ALLOC_N(char, suffix_len);
  memcpy(suffix, RSTRING_PTR(v_suffix), suffix_len);
  regex_t* suffix_re;
  OnigErrorInfo err_info;
  onig_new(&suffix_re, (const UChar*)suffix, (const UChar*)(suffix + suffix_len),
           ONIG_OPTION_NONE, ONIG_ENCODING_ASCII, ONIG_SYNTAX_RUBY, &err_info);

  std::vector<ID> _conv;
  RouteEntry e;
  e.is_sub = is_sub;
  e.prefix = prefix;
  e.prefix_len = prefix_len;
  e.suffix_re = suffix_re;
  e.suffix = suffix;
  e.suffix_len = suffix_len;
  e.controller = rb_iv_get(v_e, "@controller");
  e.id = rb_iv_get(v_e, "@id");
  e.conv = _conv;
  e.scope = rb_iv_get(v_e, "@scope");

  // conv
  VALUE v_conv = rb_iv_get(v_e, "@conv");
  VALUE* conv_ptr = RARRAY_PTR(v_conv);
  long conv_len = RARRAY_LEN(v_conv);
  if (onig_number_of_captures(suffix_re) != conv_len) {
    e.dealloc();
    rb_raise(rb_eRuntimeError, "number of captures mismatch");
  }
  for (long i = 0; i < conv_len; i++) {
    ID conv_id = SYM2ID(conv_ptr[i]);
    e.conv.push_back(conv_id);
  }

  // accept
  e.accept_exts = rb_iv_get(v_e, "@accept_exts");
  e.accept_mimes = rb_iv_get(v_e, "@accept_mimes");

  route_entries->push_back(e);
  return Qnil;
}

static VALUE ext_list_route(VALUE self) {
  // note: prevent leak with init nil
  volatile VALUE arr = Qnil;
  volatile VALUE e = Qnil;
  volatile VALUE prefix = Qnil;
  volatile VALUE conv = Qnil;

  volatile VALUE route_hash = rb_hash_new();
  for (auto j = route_map.begin(); j != route_map.end(); j++) {
    RouteEntries* route_entries = j->second;
    VALUE arr = rb_ary_new();
    rb_hash_aset(route_hash, rb_str_new2(http_method_str(j->first)), arr);
    for (auto i = route_entries->begin(); i != route_entries->end(); i++) {
      e = rb_ary_new();
      rb_ary_push(e, i->is_sub ? Qtrue : Qfalse);
      rb_ary_push(e, i->scope);
      rb_ary_push(e, rb_str_new(i->prefix, i->prefix_len));
      rb_ary_push(e, rb_str_new(i->suffix, i->suffix_len));
      rb_ary_push(e, i->controller);
      rb_ary_push(e, i->id);
      conv = rb_ary_new();
      for (size_t j = 0; j < i->conv.size(); j++) {
        rb_ary_push(conv, ID2SYM(i->conv[j]));
      }
      rb_ary_push(e, conv);
      rb_ary_push(arr, e);
    }
  }
  return route_hash;
}

static VALUE build_args(const char* suffix, std::vector<ID>& conv) {
  volatile VALUE args = rb_ary_new();
  volatile VALUE str = rb_str_new2("");
  long last_len = 0;
  for (size_t j = 0; j < conv.size(); j++) {
    const char* capture_ptr = suffix + region.beg[j+1];
    long capture_len = region.end[j+1] - region.beg[j+1];
    if (conv[j] == id_to_s) {
      rb_ary_push(args, rb_enc_str_new(capture_ptr, capture_len, u8_enc));
    } else if (capture_len == 0) {
      rb_ary_push(args, Qnil);
    } else {
      if (capture_len > last_len) {
        RESIZE_CAPA(str, capture_len);
        last_len = capture_len;
      }
      memcpy(RSTRING_PTR(str), capture_ptr, capture_len);
      STR_SET_LEN(str, capture_len);
      rb_ary_push(args, rb_funcall(str, conv[j], 0)); // hex, to_i, to_f
    }
  }
  return args;
}

static VALUE extract_ext(const char* s, long len) {
  if (s[0] != '.') {
    return Qnil;
  }
  s++;
  len--;
  for (long i = 0; i < len; i++) {
    if (!isalnum(s[i])) {
      return Qnil;
    }
  }
  return rb_str_new(s, len);
}

extern "C"
RouteResult nyara_lookup_route(enum http_method method_num, VALUE vpath, VALUE accept_arr) {
  RouteResult r = {Qnil, Qnil, Qnil, Qnil};
  auto map_iter = route_map.find(method_num);
  if (map_iter == route_map.end()) {
    return r;
  }
  RouteEntries* route_entries = map_iter->second;

  const char* path = RSTRING_PTR(vpath);
  long len = RSTRING_LEN(vpath);
  // must iterate all
  bool last_matched = false;
  auto i = route_entries->begin();
  for (; i != route_entries->end(); ++i) {
    bool matched;
    if (i->is_sub && last_matched) { // save a bit compare
      matched = last_matched;
    } else {
      matched = start_with(path, len, i->prefix, i->prefix_len);
    }
    last_matched = matched;

    if (/* prefix */ matched) {
      const char* suffix = path + i->prefix_len;
      long suffix_len = len - i->prefix_len;
      if (i->suffix_len == 0) {
        if (suffix_len) {
          r.format = extract_ext(suffix, suffix_len);
          if (r.format == Qnil) {
            break;
          }
        }
        r.args = rb_ary_new3(1, i->id);
        r.controller = i->controller;
        break;
      } else {
        long matched_len = onig_match(i->suffix_re, (const UChar*)suffix, (const UChar*)(suffix + suffix_len),
                                      (const UChar*)suffix, &region, 0);
        if (matched_len > 0) {
          if (matched_len < suffix_len) {
            r.format = extract_ext(suffix + matched_len, suffix_len);
            if (r.format == Qnil) {
              break;
            }
          }
          r.args = build_args(suffix, i->conv);
          rb_ary_push(r.args, i->id);
          r.controller = i->controller;
          break;
        }
      }
    }
  }

  if (r.controller != Qnil) {
    r.scope = i->scope;

    if (r.format == Qnil) {
      if (i->accept_exts == Qnil) {
        r.format = str_html; // not configured, just plain html
      } else {
        r.format = ext_mime_match(Qnil, accept_arr, i->accept_mimes);
        if (r.format == Qnil) {
          r.controller = Qnil; // reject if mime mismatch
        }
      }
    } else {
      if (i->accept_exts != Qnil) {
        if (!RTEST(rb_hash_aref(i->accept_exts, r.format))) {
          r.controller = Qnil; // reject if path ext mismatch
        }
      }
    }
  }
  return r;
}

static VALUE ext_lookup_route(VALUE self, VALUE method, VALUE path, VALUE accept_arr) {
  enum http_method method_num = canonicalize_http_method(method);
  volatile RouteResult r = nyara_lookup_route(method_num, path, accept_arr);
  volatile VALUE a = rb_ary_new();
  rb_ary_push(a, r.scope);
  rb_ary_push(a, r.controller);
  rb_ary_push(a, r.args);
  rb_ary_push(a, r.format);
  return a;
}

extern "C"
void Init_route(VALUE nyara, VALUE ext) {
  nyara_http_methods = rb_const_get(nyara, rb_intern("HTTP_METHODS"));
  id_to_s = rb_intern("to_s");
  u8_enc = rb_utf8_encoding();
  str_html = rb_str_new2("html");
  OBJ_FREEZE(str_html);
  rb_gc_register_mark_object(str_html);
  onig_region_init(&region);

  rb_define_singleton_method(ext, "register_route", RUBY_METHOD_FUNC(ext_register_route), 1);
  rb_define_singleton_method(ext, "clear_route", RUBY_METHOD_FUNC(ext_clear_route), 0);

  // for test
  rb_define_singleton_method(ext, "list_route", RUBY_METHOD_FUNC(ext_list_route), 0);
  rb_define_singleton_method(ext, "lookup_route", RUBY_METHOD_FUNC(ext_lookup_route), 3);
}
<commit_msg>fix missing isalnum in linux<commit_after>extern "C" {
#include "nyara.h"
}
#include <ruby/re.h>
#include <ruby/encoding.h>
#include <vector>
#include <map>
#include "inc/str_intern.h"
#ifndef isalnum
#include <cctype>
#endif

struct RouteEntry {
  // note on order: scope is supposed to be the last, but when searching, is_sub is checked first
  bool is_sub; // = last_prefix.start_with? prefix
  char* prefix;
  long prefix_len;
  regex_t *suffix_re;
  VALUE controller;
  VALUE id; // symbol
  VALUE accept_exts;  // {ext => true}
  VALUE accept_mimes; // [[m1, m2, ext]]
  std::vector<ID> conv;
  VALUE scope;
  char* suffix; // only for inspect
  long suffix_len;

  // don't make it destructor, or it could be called twice if on stack
  void dealloc() {
    if (prefix) {
      xfree(prefix);
      prefix = NULL;
    }
    if (suffix_re) {
      onig_free(suffix_re);
      suffix_re = NULL;
    }
    if (suffix) {
      xfree(suffix);
      suffix = NULL;
    }
  }
};

typedef std::vector<RouteEntry> RouteEntries;
static std::map<enum http_method, RouteEntries*> route_map;
static OnigRegion region; // we can reuse the region without worrying thread safety
static ID id_to_s;
static rb_encoding* u8_enc;
static VALUE str_html;
static VALUE nyara_http_methods;

static bool start_with(const char* a, long a_len, const char* b, long b_len) {
  if (b_len > a_len) {
    return false;
  }
  for (size_t i = 0; i < b_len; i++) {
    if (a[i] != b[i]) {
      return false;
    }
  }
  return true;
}

static enum http_method canonicalize_http_method(VALUE m) {
  VALUE method_num;
  if (TYPE(m) == T_STRING) {
    method_num = rb_hash_aref(nyara_http_methods, m);
  } else {
    method_num = m;
  }
  Check_Type(method_num, T_FIXNUM);
  return (enum http_method)FIX2INT(method_num);
}

static VALUE ext_clear_route(VALUE req) {
  for (auto i = route_map.begin(); i != route_map.end(); ++i) {
    RouteEntries* entries = i->second;
    for (auto j = entries->begin(); j != entries->end(); ++j) {
      j->dealloc();
    }
    delete entries;
  }
  route_map.clear();
  return Qnil;
}

static VALUE ext_register_route(VALUE self, VALUE v_e) {
  // get route entries
  enum http_method m = canonicalize_http_method(rb_iv_get(v_e, "@http_method"));
  RouteEntries* route_entries;
  auto map_iter = route_map.find(m);
  if (map_iter == route_map.end()) {
    route_entries = new RouteEntries();
    route_map[m] = route_entries;
  } else {
    route_entries = map_iter->second;
  }

  // prefix
  VALUE v_prefix = rb_iv_get(v_e, "@prefix");
  long prefix_len = RSTRING_LEN(v_prefix);
  char* prefix = ALLOC_N(char, prefix_len);
  memcpy(prefix, RSTRING_PTR(v_prefix), prefix_len);

  // check if prefix is substring of last entry
  bool is_sub = false;
  if (route_entries->size()) {
    is_sub = start_with(route_entries->rbegin()->prefix, route_entries->rbegin()->prefix_len, prefix, prefix_len);
  }

  // suffix
  VALUE v_suffix = rb_iv_get(v_e, "@suffix");
  long suffix_len = RSTRING_LEN(v_suffix);
  char* suffix = ALLOC_N(char, suffix_len);
  memcpy(suffix, RSTRING_PTR(v_suffix), suffix_len);
  regex_t* suffix_re;
  OnigErrorInfo err_info;
  onig_new(&suffix_re, (const UChar*)suffix, (const UChar*)(suffix + suffix_len),
           ONIG_OPTION_NONE, ONIG_ENCODING_ASCII, ONIG_SYNTAX_RUBY, &err_info);

  std::vector<ID> _conv;
  RouteEntry e;
  e.is_sub = is_sub;
  e.prefix = prefix;
  e.prefix_len = prefix_len;
  e.suffix_re = suffix_re;
  e.suffix = suffix;
  e.suffix_len = suffix_len;
  e.controller = rb_iv_get(v_e, "@controller");
  e.id = rb_iv_get(v_e, "@id");
  e.conv = _conv;
  e.scope = rb_iv_get(v_e, "@scope");

  // conv
  VALUE v_conv = rb_iv_get(v_e, "@conv");
  VALUE* conv_ptr = RARRAY_PTR(v_conv);
  long conv_len = RARRAY_LEN(v_conv);
  if (onig_number_of_captures(suffix_re) != conv_len) {
    e.dealloc();
    rb_raise(rb_eRuntimeError, "number of captures mismatch");
  }
  for (long i = 0; i < conv_len; i++) {
    ID conv_id = SYM2ID(conv_ptr[i]);
    e.conv.push_back(conv_id);
  }

  // accept
  e.accept_exts = rb_iv_get(v_e, "@accept_exts");
  e.accept_mimes = rb_iv_get(v_e, "@accept_mimes");

  route_entries->push_back(e);
  return Qnil;
}

static VALUE ext_list_route(VALUE self) {
  // note: prevent leak with init nil
  volatile VALUE arr = Qnil;
  volatile VALUE e = Qnil;
  volatile VALUE prefix = Qnil;
  volatile VALUE conv = Qnil;

  volatile VALUE route_hash = rb_hash_new();
  for (auto j = route_map.begin(); j != route_map.end(); j++) {
    RouteEntries* route_entries = j->second;
    VALUE arr = rb_ary_new();
    rb_hash_aset(route_hash, rb_str_new2(http_method_str(j->first)), arr);
    for (auto i = route_entries->begin(); i != route_entries->end(); i++) {
      e = rb_ary_new();
      rb_ary_push(e, i->is_sub ? Qtrue : Qfalse);
      rb_ary_push(e, i->scope);
      rb_ary_push(e, rb_str_new(i->prefix, i->prefix_len));
      rb_ary_push(e, rb_str_new(i->suffix, i->suffix_len));
      rb_ary_push(e, i->controller);
      rb_ary_push(e, i->id);
      conv = rb_ary_new();
      for (size_t j = 0; j < i->conv.size(); j++) {
        rb_ary_push(conv, ID2SYM(i->conv[j]));
      }
      rb_ary_push(e, conv);
      rb_ary_push(arr, e);
    }
  }
  return route_hash;
}

static VALUE build_args(const char* suffix, std::vector<ID>& conv) {
  volatile VALUE args = rb_ary_new();
  volatile VALUE str = rb_str_new2("");
  long last_len = 0;
  for (size_t j = 0; j < conv.size(); j++) {
    const char* capture_ptr = suffix + region.beg[j+1];
    long capture_len = region.end[j+1] - region.beg[j+1];
    if (conv[j] == id_to_s) {
      rb_ary_push(args, rb_enc_str_new(capture_ptr, capture_len, u8_enc));
    } else if (capture_len == 0) {
      rb_ary_push(args, Qnil);
    } else {
      if (capture_len > last_len) {
        RESIZE_CAPA(str, capture_len);
        last_len = capture_len;
      }
      memcpy(RSTRING_PTR(str), capture_ptr, capture_len);
      STR_SET_LEN(str, capture_len);
      rb_ary_push(args, rb_funcall(str, conv[j], 0)); // hex, to_i, to_f
    }
  }
  return args;
}

static VALUE extract_ext(const char* s, long len) {
  if (s[0] != '.') {
    return Qnil;
  }
  s++;
  len--;
  for (long i = 0; i < len; i++) {
    if (!isalnum(s[i])) {
      return Qnil;
    }
  }
  return rb_str_new(s, len);
}

extern "C"
RouteResult nyara_lookup_route(enum http_method method_num, VALUE vpath, VALUE accept_arr) {
  RouteResult r = {Qnil, Qnil, Qnil, Qnil};
  auto map_iter = route_map.find(method_num);
  if (map_iter == route_map.end()) {
    return r;
  }
  RouteEntries* route_entries = map_iter->second;

  const char* path = RSTRING_PTR(vpath);
  long len = RSTRING_LEN(vpath);
  // must iterate all
  bool last_matched = false;
  auto i = route_entries->begin();
  for (; i != route_entries->end(); ++i) {
    bool matched;
    if (i->is_sub && last_matched) { // save a bit compare
      matched = last_matched;
    } else {
      matched = start_with(path, len, i->prefix, i->prefix_len);
    }
    last_matched = matched;

    if (/* prefix */ matched) {
      const char* suffix = path + i->prefix_len;
      long suffix_len = len - i->prefix_len;
      if (i->suffix_len == 0) {
        if (suffix_len) {
          r.format = extract_ext(suffix, suffix_len);
          if (r.format == Qnil) {
            break;
          }
        }
        r.args = rb_ary_new3(1, i->id);
        r.controller = i->controller;
        break;
      } else {
        long matched_len = onig_match(i->suffix_re, (const UChar*)suffix, (const UChar*)(suffix + suffix_len),
                                      (const UChar*)suffix, &region, 0);
        if (matched_len > 0) {
          if (matched_len < suffix_len) {
            r.format = extract_ext(suffix + matched_len, suffix_len);
            if (r.format == Qnil) {
              break;
            }
          }
          r.args = build_args(suffix, i->conv);
          rb_ary_push(r.args, i->id);
          r.controller = i->controller;
          break;
        }
      }
    }
  }

  if (r.controller != Qnil) {
    r.scope = i->scope;

    if (r.format == Qnil) {
      if (i->accept_exts == Qnil) {
        r.format = str_html; // not configured, just plain html
      } else {
        r.format = ext_mime_match(Qnil, accept_arr, i->accept_mimes);
        if (r.format == Qnil) {
          r.controller = Qnil; // reject if mime mismatch
        }
      }
    } else {
      if (i->accept_exts != Qnil) {
        if (!RTEST(rb_hash_aref(i->accept_exts, r.format))) {
          r.controller = Qnil; // reject if path ext mismatch
        }
      }
    }
  }
  return r;
}

static VALUE ext_lookup_route(VALUE self, VALUE method, VALUE path, VALUE accept_arr) {
  enum http_method method_num = canonicalize_http_method(method);
  volatile RouteResult r = nyara_lookup_route(method_num, path, accept_arr);
  volatile VALUE a = rb_ary_new();
  rb_ary_push(a, r.scope);
  rb_ary_push(a, r.controller);
  rb_ary_push(a, r.args);
  rb_ary_push(a, r.format);
  return a;
}

extern "C"
void Init_route(VALUE nyara, VALUE ext) {
  nyara_http_methods = rb_const_get(nyara, rb_intern("HTTP_METHODS"));
  id_to_s = rb_intern("to_s");
  u8_enc = rb_utf8_encoding();
  str_html = rb_str_new2("html");
  OBJ_FREEZE(str_html);
  rb_gc_register_mark_object(str_html);
  onig_region_init(&region);

  rb_define_singleton_method(ext, "register_route", RUBY_METHOD_FUNC(ext_register_route), 1);
  rb_define_singleton_method(ext, "clear_route", RUBY_METHOD_FUNC(ext_clear_route), 0);

  // for test
  rb_define_singleton_method(ext, "list_route", RUBY_METHOD_FUNC(ext_list_route), 0);
  rb_define_singleton_method(ext, "lookup_route", RUBY_METHOD_FUNC(ext_lookup_route), 3);
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <stdint.h>
#include <stdio.h>

namespace {

  const char kToplevel[] = "$total$";
  const char kOverhead[] = "$overhead$";
  const char kIgnore[] = "$ignore$";

  struct OpInfo {
    std::string op_type;
    std::string op_name;
    std::string parent_type;
    std::string parent_name;
    // number of times called
    int64_t count;
    // ticks used (processor specific, no fixed time interval)
    int64_t ticks;
    // nsec is actually only measured for $total$;
    // it's (approximated) calculated for all others
    double nsec;
    // percentage of total ticks, [0.0..1.0]
    double percent;
    // ticks/nsec/percent used by this op alone (not including callees)
    int64_t ticks_only;
    double nsec_only;
    double percent_only;

    OpInfo()
      : count(0),
        ticks(0),
        nsec(0.0),
        percent(0.0),
        ticks_only(0),
        nsec_only(0.0),
        percent_only(0.0) {}
  };

  // Outer map is keyed by function name,
  // inner map is keyed by op_type + op_name
  typedef std::map<std::string, OpInfo> OpInfoMap;
  typedef std::map<std::string, OpInfoMap> FuncInfoMap;

  std::string qualified_name(const std::string& op_type, const std::string& op_name) {
    // Arbitrary, just join type + name
    return op_type + ":" + op_name;
  }

  // How is it posible that there is no string-split function in the C++
  // standard library?
  std::vector<std::string> Split(const std::string& s, char delim) {
    std::vector<std::string> v;
    std::istringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        v.push_back(item);
    }
    return v;
  }

  bool HasOpt(char** begin, char** end, const std::string& opt) {
    return std::find(begin, end, opt) != end;
  }

  // look for string "opt"; if found, return subsequent string;
  // if not found, return empty string.
  std::string GetOpt(char** begin, char** end, const std::string& opt) {
    char** it = std::find(begin, end, opt);
    if (it != end && ++it != end) {
        return std::string(*it);
    }
    return std::string();
  }

  void ProcessLine(const std::string& s, FuncInfoMap& info, bool accumulate_runs) {
    std::vector<std::string> v = Split(s, ' ');
    if (v.size() < 8) {
      return;
    }
    // Some environments (e.g. Android logging) will emit a prefix
    // for each line; skip the first few words we see before
    // deciding to ignore the line.
    int first = -1;
    for (int i = 0; i < 4; ++i) {
      if (v[i] == "halide_profiler") {
        first = i;
        break;
      }
    }
    if (first < 0) {
      return;
    }
    const std::string& metric = v[first + 1];
    const std::string& func_name = v[first + 2];
    const std::string& op_type = v[first + 3];
    const std::string& op_name = v[first + 4];
    const std::string& parent_type = v[first + 5];
    const std::string& parent_name = v[first + 6];
    if (op_type == kIgnore || op_name == kIgnore) {
      return;
    }
    std::istringstream value_stream(v[first + 7]);
    int64_t value;
    value_stream >> value;
    OpInfoMap& op_info_map = info[func_name];
    OpInfo& op_info = op_info_map[qualified_name(op_type, op_name)];
    op_info.op_type = op_type;
    op_info.op_name = op_name;
    op_info.parent_type = parent_type;
    op_info.parent_name = parent_name;
    if (metric == "count") {
      op_info.count = (accumulate_runs ? op_info.count : 0) + value;
    } else if (metric == "ticks") {
      op_info.ticks = (accumulate_runs ? op_info.ticks : 0) + value;
    } else if (metric == "nsec") {
      op_info.nsec = (accumulate_runs ? op_info.nsec : 0) + value;
    }
  }

  typedef std::map<std::string, std::vector<OpInfo*> > ChildMap;

  int64_t AdjustOverhead(OpInfo& op_info, ChildMap& child_map, double overhead_ticks_avg) {
    int64_t overhead_ticks = op_info.count * overhead_ticks_avg;

    op_info.ticks_only -= overhead_ticks;

    std::string qual_name = qualified_name(op_info.op_type, op_info.op_name);
    const std::vector<OpInfo*>& children = child_map[qual_name];
    for (std::vector<OpInfo*>::const_iterator it = children.begin(); it != children.end(); ++it) {
      OpInfo* c = *it;
      int64_t child_overhead = AdjustOverhead(*c, child_map, overhead_ticks_avg);
      overhead_ticks += child_overhead;
    }

    op_info.ticks -= overhead_ticks;

    return overhead_ticks;
  }

  void FinishOpInfo(OpInfoMap& op_info_map, bool adjust_for_overhead) {

    std::string toplevel_qual_name = qualified_name(kToplevel, kToplevel);
    OpInfo& total = op_info_map[toplevel_qual_name];
    total.percent = 1.0;

    double ticks_per_nsec = (double)total.ticks / (double)total.nsec;

    // Note that overhead (if present) is measured outside the rest
    // of the "total", so it should not be included (or subtracted from)
    // the total.
    double overhead_ticks_avg = 0;
    std::string overhead_qual_name = qualified_name(kOverhead, kOverhead);
    OpInfoMap::iterator it = op_info_map.find(overhead_qual_name);
    if (it != op_info_map.end()) {
      OpInfo overhead = it->second;
      overhead_ticks_avg = (double)overhead.ticks / (double)overhead.count;
      op_info_map.erase(it);
    }

    ChildMap child_map;
    for (OpInfoMap::iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      OpInfo& op_info = o->second;
      std::string parent_qual_name = qualified_name(op_info.parent_type, op_info.parent_name);
      child_map[parent_qual_name].push_back(&op_info);
    }

    for (OpInfoMap::iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      OpInfo& op_info = o->second;
      op_info.ticks_only = op_info.ticks;
      const std::vector<OpInfo*>& children = child_map[o->first];
      for (std::vector<OpInfo*>::const_iterator it = children.begin(); it != children.end(); ++it) {
        OpInfo* c = *it;
        op_info.ticks_only -= c->ticks;
      }
    }

    if (adjust_for_overhead) {
      // Adjust values to account for profiling overhead
      AdjustOverhead(total, child_map, overhead_ticks_avg);
    }

    // Calc the derived fields
    for (OpInfoMap::iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      OpInfo& op_info = o->second;
      op_info.nsec = op_info.ticks / ticks_per_nsec;
      op_info.nsec_only = op_info.ticks_only / ticks_per_nsec;
      op_info.percent = (double)op_info.ticks / (double)total.ticks;
      op_info.percent_only = (double)op_info.ticks_only / (double)total.ticks;
    }
  }

  template <typename CmpFunc>
  std::vector<OpInfo> SortOpInfo(const OpInfoMap& op_info_map, CmpFunc cmp) {
    std::vector<OpInfo> v;
    for (OpInfoMap::const_iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      v.push_back(o->second);
    }
    // Note: using reverse iterators to get a descending sort
    std::sort(v.rbegin(), v.rend(), cmp);
    return v;
  }

  bool by_count(const OpInfo& a, const OpInfo& b) { return a.count < b.count; }
  bool by_ticks(const OpInfo& a, const OpInfo& b) { return a.ticks < b.ticks; }
  bool by_ticks_only(const OpInfo& a, const OpInfo& b) { return a.ticks_only < b.ticks_only; }

}  // namespace

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

  if (HasOpt(argv, argv + argc, "-h")) {
    printf("HalideProf [-f funcname] [-sort c|t|to] [-top N] [-overhead=0|1] [-accumulate=[0|1]] < profiledata\n");
    return 0;
  }

  std::string func_name_filter = GetOpt(argv, argv + argc, "-f");

  bool (*sort_by_func)(const OpInfo& a, const OpInfo& b);
  std::string sort_by = GetOpt(argv, argv + argc, "-sort");
  if (sort_by.empty() || sort_by == "to") {
    sort_by_func = by_ticks_only;
  } else if (sort_by == "t") {
    sort_by_func = by_ticks;
  } else if (sort_by == "c") {
    sort_by_func = by_count;
  } else {
    std::cerr << "Unknown value for -sort: " << sort_by << "\n";
    exit(-1);
  }

  int32_t top_n = 10;
  std::string top_n_str = GetOpt(argv, argv + argc, "-top");
  if (!top_n_str.empty()) {
    std::istringstream(top_n_str) >> top_n;
  }

  // It's rare that you wouldn't want to try to adjust the times
  // to minimize the effect profiling overhead, but just in case,
  // allow -overhead 0
  int32_t adjust_for_overhead = 1;
  std::string adjust_for_overhead_str = GetOpt(argv, argv + argc, "-overhead");
  if (!adjust_for_overhead_str.empty()) {
    std::istringstream(adjust_for_overhead_str) >> adjust_for_overhead;
  }

  int32_t accumulate_runs = 0;
  std::string accumulate_runs_str = GetOpt(argv, argv + argc, "-accumulate");
  if (!accumulate_runs_str.empty()) {
    std::istringstream(accumulate_runs_str) >> accumulate_runs;
  }

  FuncInfoMap func_info_map;
  std::string line;
  while (std::getline(std::cin, line)) {
    ProcessLine(line, func_info_map, accumulate_runs);
  }

  for (FuncInfoMap::iterator f = func_info_map.begin(); f != func_info_map.end(); ++f) {
    FinishOpInfo(f->second, adjust_for_overhead != 0);
  }

  for (FuncInfoMap::iterator f = func_info_map.begin(); f != func_info_map.end(); ++f) {
    const std::string& func_name = f->first;
    if (!func_name_filter.empty() && func_name_filter != func_name) {
      continue;
    }
    std::cout << "Func: " << func_name << "\n";
    std::cout << "--------------------------\n";
    std::cout
      << std::setw(10) << std::left << "op_type"
      << std::setw(40) << std::left << "op_name"
      << std::setw(16) << std::right << "count"
      << std::setw(16) << "ticks-cum"
      << std::setw(12) << "msec-cum"
      << std::setw(8) << std::fixed << "%-cum"
      << std::setw(16) << "ticks-only"
      << std::setw(12) << "msec-only"
      << std::setw(8) << std::fixed << "%-only"
      << "\n";
    std::vector<OpInfo> op_info = SortOpInfo(f->second, sort_by_func);
    for (std::vector<OpInfo>::const_iterator o = op_info.begin(); o != op_info.end(); ++o) {
      const OpInfo& op_info = *o;
      std::cout
        << std::setw(10) << std::left << op_info.op_type
        << std::setw(40) << std::left << op_info.op_name
        << std::setw(16) << std::right << op_info.count
        << std::setw(16) << op_info.ticks
        << std::setw(12) << std::setprecision(2) << std::fixed << (op_info.nsec / 1000000.0)
        << std::setw(8) << std::setprecision(2) << std::fixed << (op_info.percent * 100.0)
        << std::setw(16) << op_info.ticks_only
        << std::setw(12) << std::setprecision(2) << std::fixed << (op_info.nsec_only / 1000000.0)
        << std::setw(8) << std::setprecision(2) << std::fixed << (op_info.percent_only * 100.0)
        << "\n";
      if (--top_n <= 0) {
        break;
      }
    }
  }
}
<commit_msg>Adjusted overhead adjustment<commit_after>#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <stdint.h>
#include <stdio.h>

namespace {

  const char kToplevel[] = "$total$";
  const char kOverhead[] = "$overhead$";
  const char kIgnore[] = "$ignore$";

  struct OpInfo {
    std::string op_type;
    std::string op_name;
    std::string parent_type;
    std::string parent_name;
    // number of times called
    int64_t count;
    // ticks used (processor specific, no fixed time interval)
    int64_t ticks;
    // nsec is actually only measured for $total$;
    // it's (approximated) calculated for all others
    double nsec;
    // percentage of total ticks, [0.0..1.0]
    double percent;
    // ticks/nsec/percent used by this op alone (not including callees)
    int64_t ticks_only;
    double nsec_only;
    double percent_only;

    OpInfo()
      : count(0),
        ticks(0),
        nsec(0.0),
        percent(0.0),
        ticks_only(0),
        nsec_only(0.0),
        percent_only(0.0) {}
  };

  // Outer map is keyed by function name,
  // inner map is keyed by op_type + op_name
  typedef std::map<std::string, OpInfo> OpInfoMap;
  typedef std::map<std::string, OpInfoMap> FuncInfoMap;

  std::string qualified_name(const std::string& op_type, const std::string& op_name) {
    // Arbitrary, just join type + name
    return op_type + ":" + op_name;
  }

  // How is it posible that there is no string-split function in the C++
  // standard library?
  std::vector<std::string> Split(const std::string& s, char delim) {
    std::vector<std::string> v;
    std::istringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        v.push_back(item);
    }
    return v;
  }

  bool HasOpt(char** begin, char** end, const std::string& opt) {
    return std::find(begin, end, opt) != end;
  }

  // look for string "opt"; if found, return subsequent string;
  // if not found, return empty string.
  std::string GetOpt(char** begin, char** end, const std::string& opt) {
    char** it = std::find(begin, end, opt);
    if (it != end && ++it != end) {
        return std::string(*it);
    }
    return std::string();
  }

  void ProcessLine(const std::string& s, FuncInfoMap& info, bool accumulate_runs) {
    std::vector<std::string> v = Split(s, ' ');
    if (v.size() < 8) {
      return;
    }
    // Some environments (e.g. Android logging) will emit a prefix
    // for each line; skip the first few words we see before
    // deciding to ignore the line.
    int first = -1;
    for (int i = 0; i < 4; ++i) {
      if (v[i] == "halide_profiler") {
        first = i;
        break;
      }
    }
    if (first < 0) {
      return;
    }
    const std::string& metric = v[first + 1];
    const std::string& func_name = v[first + 2];
    const std::string& op_type = v[first + 3];
    const std::string& op_name = v[first + 4];
    const std::string& parent_type = v[first + 5];
    const std::string& parent_name = v[first + 6];
    if (op_type == kIgnore || op_name == kIgnore) {
      return;
    }
    std::istringstream value_stream(v[first + 7]);
    int64_t value;
    value_stream >> value;
    OpInfoMap& op_info_map = info[func_name];
    OpInfo& op_info = op_info_map[qualified_name(op_type, op_name)];
    op_info.op_type = op_type;
    op_info.op_name = op_name;
    op_info.parent_type = parent_type;
    op_info.parent_name = parent_name;
    if (metric == "count") {
      op_info.count = (accumulate_runs ? op_info.count : 0) + value;
    } else if (metric == "ticks") {
      op_info.ticks = (accumulate_runs ? op_info.ticks : 0) + value;
    } else if (metric == "nsec") {
      op_info.nsec = (accumulate_runs ? op_info.nsec : 0) + value;
    }
  }

  typedef std::map<std::string, std::vector<OpInfo*> > ChildMap;

  int64_t AdjustOverhead(OpInfo& op_info, ChildMap& child_map, double overhead_ticks_avg) {
    int64_t overhead_ticks = op_info.count * overhead_ticks_avg;

    op_info.ticks_only -= overhead_ticks;

    std::string qual_name = qualified_name(op_info.op_type, op_info.op_name);
    const std::vector<OpInfo*>& children = child_map[qual_name];
    for (std::vector<OpInfo*>::const_iterator it = children.begin(); it != children.end(); ++it) {
      OpInfo* c = *it;
      int64_t child_overhead = AdjustOverhead(*c, child_map, overhead_ticks_avg);
      overhead_ticks += child_overhead;
    }

    op_info.ticks -= overhead_ticks;

    return overhead_ticks;
  }

  void FinishOpInfo(OpInfoMap& op_info_map, bool adjust_for_overhead) {

    std::string toplevel_qual_name = qualified_name(kToplevel, kToplevel);
    OpInfo& total = op_info_map[toplevel_qual_name];
    total.percent = 1.0;

    double ticks_per_nsec = (double)total.ticks / (double)total.nsec;

    // Note that overhead (if present) is measured outside the rest
    // of the "total", so it should not be included (or subtracted from)
    // the total.
    double overhead_ticks_avg = 0;
    std::string overhead_qual_name = qualified_name(kOverhead, kOverhead);
    OpInfoMap::iterator it = op_info_map.find(overhead_qual_name);
    if (it != op_info_map.end()) {
      OpInfo overhead = it->second;
      overhead_ticks_avg = (double)overhead.ticks / ((double)overhead.count * 2.0);
      op_info_map.erase(it);
    }

    ChildMap child_map;
    for (OpInfoMap::iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      OpInfo& op_info = o->second;
      std::string parent_qual_name = qualified_name(op_info.parent_type, op_info.parent_name);
      child_map[parent_qual_name].push_back(&op_info);
    }

    for (OpInfoMap::iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      OpInfo& op_info = o->second;
      op_info.ticks_only = op_info.ticks;
      const std::vector<OpInfo*>& children = child_map[o->first];
      for (std::vector<OpInfo*>::const_iterator it = children.begin(); it != children.end(); ++it) {
        OpInfo* c = *it;
        op_info.ticks_only -= c->ticks;
      }
    }

    if (adjust_for_overhead) {
      // Adjust values to account for profiling overhead
      AdjustOverhead(total, child_map, overhead_ticks_avg);
    }

    // Calc the derived fields
    for (OpInfoMap::iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      OpInfo& op_info = o->second;
      op_info.nsec = op_info.ticks / ticks_per_nsec;
      op_info.nsec_only = op_info.ticks_only / ticks_per_nsec;
      op_info.percent = (double)op_info.ticks / (double)total.ticks;
      op_info.percent_only = (double)op_info.ticks_only / (double)total.ticks;
    }
  }

  template <typename CmpFunc>
  std::vector<OpInfo> SortOpInfo(const OpInfoMap& op_info_map, CmpFunc cmp) {
    std::vector<OpInfo> v;
    for (OpInfoMap::const_iterator o = op_info_map.begin(); o != op_info_map.end(); ++o) {
      v.push_back(o->second);
    }
    // Note: using reverse iterators to get a descending sort
    std::sort(v.rbegin(), v.rend(), cmp);
    return v;
  }

  bool by_count(const OpInfo& a, const OpInfo& b) { return a.count < b.count; }
  bool by_ticks(const OpInfo& a, const OpInfo& b) { return a.ticks < b.ticks; }
  bool by_ticks_only(const OpInfo& a, const OpInfo& b) { return a.ticks_only < b.ticks_only; }

}  // namespace

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

  if (HasOpt(argv, argv + argc, "-h")) {
    printf("HalideProf [-f funcname] [-sort c|t|to] [-top N] [-overhead=0|1] [-accumulate=[0|1]] < profiledata\n");
    return 0;
  }

  std::string func_name_filter = GetOpt(argv, argv + argc, "-f");

  bool (*sort_by_func)(const OpInfo& a, const OpInfo& b);
  std::string sort_by = GetOpt(argv, argv + argc, "-sort");
  if (sort_by.empty() || sort_by == "to") {
    sort_by_func = by_ticks_only;
  } else if (sort_by == "t") {
    sort_by_func = by_ticks;
  } else if (sort_by == "c") {
    sort_by_func = by_count;
  } else {
    std::cerr << "Unknown value for -sort: " << sort_by << "\n";
    exit(-1);
  }

  int32_t top_n = 10;
  std::string top_n_str = GetOpt(argv, argv + argc, "-top");
  if (!top_n_str.empty()) {
    std::istringstream(top_n_str) >> top_n;
  }

  // It's rare that you wouldn't want to try to adjust the times
  // to minimize the effect profiling overhead, but just in case,
  // allow -overhead 0
  int32_t adjust_for_overhead = 1;
  std::string adjust_for_overhead_str = GetOpt(argv, argv + argc, "-overhead");
  if (!adjust_for_overhead_str.empty()) {
    std::istringstream(adjust_for_overhead_str) >> adjust_for_overhead;
  }

  int32_t accumulate_runs = 0;
  std::string accumulate_runs_str = GetOpt(argv, argv + argc, "-accumulate");
  if (!accumulate_runs_str.empty()) {
    std::istringstream(accumulate_runs_str) >> accumulate_runs;
  }

  FuncInfoMap func_info_map;
  std::string line;
  while (std::getline(std::cin, line)) {
    ProcessLine(line, func_info_map, accumulate_runs);
  }

  for (FuncInfoMap::iterator f = func_info_map.begin(); f != func_info_map.end(); ++f) {
    FinishOpInfo(f->second, adjust_for_overhead != 0);
  }

  for (FuncInfoMap::iterator f = func_info_map.begin(); f != func_info_map.end(); ++f) {
    const std::string& func_name = f->first;
    if (!func_name_filter.empty() && func_name_filter != func_name) {
      continue;
    }
    std::cout << "Func: " << func_name << "\n";
    std::cout << "--------------------------\n";
    std::cout
      << std::setw(10) << std::left << "op_type"
      << std::setw(40) << std::left << "op_name"
      << std::setw(16) << std::right << "count"
      << std::setw(16) << "ticks-cum"
      << std::setw(12) << "msec-cum"
      << std::setw(8) << std::fixed << "%-cum"
      << std::setw(16) << "ticks-only"
      << std::setw(12) << "msec-only"
      << std::setw(8) << std::fixed << "%-only"
      << "\n";
    std::vector<OpInfo> op_info = SortOpInfo(f->second, sort_by_func);
    for (std::vector<OpInfo>::const_iterator o = op_info.begin(); o != op_info.end(); ++o) {
      const OpInfo& op_info = *o;
      std::cout
        << std::setw(10) << std::left << op_info.op_type
        << std::setw(40) << std::left << op_info.op_name
        << std::setw(16) << std::right << op_info.count
        << std::setw(16) << op_info.ticks
        << std::setw(12) << std::setprecision(2) << std::fixed << (op_info.nsec / 1000000.0)
        << std::setw(8) << std::setprecision(2) << std::fixed << (op_info.percent * 100.0)
        << std::setw(16) << op_info.ticks_only
        << std::setw(12) << std::setprecision(2) << std::fixed << (op_info.nsec_only / 1000000.0)
        << std::setw(8) << std::setprecision(2) << std::fixed << (op_info.percent_only * 100.0)
        << "\n";
      if (--top_n <= 0) {
        break;
      }
    }
  }
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

bool socketError = false;

int DDV_Listen(int port){
  int s = socket(AF_INET, SOCK_STREAM, 0);

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);//port 8888
  inet_pton(AF_INET, "0.0.0.0", &addr.sin_addr);//listen on all interfaces
  int ret = bind(s, (sockaddr*)&addr, sizeof(addr));//bind to all interfaces, chosen port
  if (ret == 0){
    ret = listen(s, 100);//start listening, backlog of 100 allowed
    if (ret == 0){
      return s;
    }else{
      printf("Listen failed! Error: %s\n", strerror(errno));
      close(s);
      return 0;
    }
  }else{
    printf("Binding failed! Error: %s\n", strerror(errno));
    close(s);
    return 0;
  }
}

int DDV_Accept(int sock){
  return accept(sock, 0, 0);
}

bool DDV_write(void * buffer, int width, int count, int sock){
  bool r = (send(sock, buffer, width*count, 0) == width*count);
  if (!r){socketError = true}
  return r;
}

bool DDV_read(void * buffer, int width, int count, int sock){
  bool r = (recv(sock, buffer, width*count, 0) == width*count);
  if (!r){socketError = true}
  return r;
}
<commit_msg>Nog een poging...<commit_after>#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

bool socketError = false;

int DDV_Listen(int port){
  int s = socket(AF_INET, SOCK_STREAM, 0);

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);//port 8888
  inet_pton(AF_INET, "0.0.0.0", &addr.sin_addr);//listen on all interfaces
  int ret = bind(s, (sockaddr*)&addr, sizeof(addr));//bind to all interfaces, chosen port
  if (ret == 0){
    ret = listen(s, 100);//start listening, backlog of 100 allowed
    if (ret == 0){
      return s;
    }else{
      printf("Listen failed! Error: %s\n", strerror(errno));
      close(s);
      return 0;
    }
  }else{
    printf("Binding failed! Error: %s\n", strerror(errno));
    close(s);
    return 0;
  }
}

int DDV_Accept(int sock){
  return accept(sock, 0, 0);
}

bool DDV_write(void * buffer, int width, int count, int sock){
  bool r = (send(sock, buffer, width*count, 0) == width*count);
  if (!r){socketError = true;}
  return r;
}

bool DDV_read(void * buffer, int width, int count, int sock){
  bool r = (recv(sock, buffer, width*count, 0) == width*count);
  if (!r){socketError = true;}
  return r;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkExecutor.h"
#include "include/gpu/GrContextOptions.h"
#include "tools/flags/CommonFlags.h"

DEFINE_int(gpuThreads,
             2,
             "Create this many extra threads to assist with GPU work, "
             "including software path rendering. Defaults to two.");

static DEFINE_bool(cachePathMasks, true,
                   "Allows path mask textures to be cached in GPU configs.");
static DEFINE_bool(allPathsVolatile, false,
                   "Causes all GPU paths to be processed as if 'setIsVolatile' had been called.");

static DEFINE_bool(gs, true, "Enables support for geometry shaders (if hw allows).");
static DEFINE_bool(hwtess, false, "Enables support for tessellation shaders (if hw allows.).");

static DEFINE_int(maxTessellationSegments, 0,
                  "Overrides the max number of tessellation segments supported by the caps.");

static DEFINE_bool(alwaysHwTess, false,
        "Always try to use hardware tessellation, regardless of how small a path may be.");

static DEFINE_string(pr, "",
              "Set of enabled gpu path renderers. Defined as a list of: "
              "[~]none [~]dashline [~]ccpr [~]aahairline [~]aaconvex [~]aalinearizing "
              "[~]small [~]tri [~]tess [~]all");

static DEFINE_int(internalSamples, 4, "Number of samples for internal draws that use MSAA.");

static DEFINE_bool(disableDriverCorrectnessWorkarounds, false,
                   "Disables all GPU driver correctness workarounds");

static DEFINE_bool(dontReduceOpsTaskSplitting, false,
                   "Don't reorder tasks to reduce render passes");

static DEFINE_int(gpuResourceCacheLimit, -1,
                  "Maximum number of bytes to use for budgeted GPU resources. "
                  "Default is -1, which means GrResourceCache::kDefaultMaxSize.");

static GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
    if (!strcmp(name, "none")) {
        return GpuPathRenderers::kNone;
    } else if (!strcmp(name, "dashline")) {
        return GpuPathRenderers::kDashLine;
    } else if (!strcmp(name, "ccpr")) {
        return GpuPathRenderers::kCoverageCounting;
    } else if (!strcmp(name, "aahairline")) {
        return GpuPathRenderers::kAAHairline;
    } else if (!strcmp(name, "aaconvex")) {
        return GpuPathRenderers::kAAConvex;
    } else if (!strcmp(name, "aalinearizing")) {
        return GpuPathRenderers::kAALinearizing;
    } else if (!strcmp(name, "small")) {
        return GpuPathRenderers::kSmall;
    } else if (!strcmp(name, "tri")) {
        return GpuPathRenderers::kTriangulating;
    } else if (!strcmp(name, "tess")) {
        return GpuPathRenderers::kTessellation;
    } else if (!strcmp(name, "default")) {
        return GpuPathRenderers::kDefault;
    }
    SK_ABORT("error: unknown named path renderer \"%s\"\n", name);
}

static GpuPathRenderers collect_gpu_path_renderers_from_flags() {
    if (FLAGS_pr.isEmpty()) {
        return GpuPathRenderers::kDefault;
    }

    GpuPathRenderers gpuPathRenderers = ('~' == FLAGS_pr[0][0])
            ? GpuPathRenderers::kDefault
            : GpuPathRenderers::kNone;

    for (int i = 0; i < FLAGS_pr.count(); ++i) {
        const char* name = FLAGS_pr[i];
        if (name[0] == '~') {
            gpuPathRenderers &= ~get_named_pathrenderers_flags(&name[1]);
        } else {
            gpuPathRenderers |= get_named_pathrenderers_flags(name);
        }
    }
    return gpuPathRenderers;
}

void SetCtxOptionsFromCommonFlags(GrContextOptions* ctxOptions) {
    static std::unique_ptr<SkExecutor> gGpuExecutor = (0 != FLAGS_gpuThreads)
        ? SkExecutor::MakeFIFOThreadPool(FLAGS_gpuThreads)
        : nullptr;

    ctxOptions->fExecutor                            = gGpuExecutor.get();
    ctxOptions->fAllowPathMaskCaching                = FLAGS_cachePathMasks;
    ctxOptions->fAllPathsVolatile                    = FLAGS_allPathsVolatile;
    ctxOptions->fSuppressGeometryShaders             = !FLAGS_gs;
    ctxOptions->fEnableExperimentalHardwareTessellation = FLAGS_hwtess;
    ctxOptions->fMaxTessellationSegmentsOverride     = FLAGS_maxTessellationSegments;
    ctxOptions->fAlwaysPreferHardwareTessellation    = FLAGS_alwaysHwTess;
    ctxOptions->fGpuPathRenderers                    = collect_gpu_path_renderers_from_flags();
    ctxOptions->fInternalMultisampleCount            = FLAGS_internalSamples;
    ctxOptions->fDisableDriverCorrectnessWorkarounds = FLAGS_disableDriverCorrectnessWorkarounds;
    ctxOptions->fResourceCacheLimitOverride          = FLAGS_gpuResourceCacheLimit;

    ctxOptions->fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
}
<commit_msg>Revert "Temporarily disable reordering on bots again"<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkExecutor.h"
#include "include/gpu/GrContextOptions.h"
#include "tools/flags/CommonFlags.h"

DEFINE_int(gpuThreads,
             2,
             "Create this many extra threads to assist with GPU work, "
             "including software path rendering. Defaults to two.");

static DEFINE_bool(cachePathMasks, true,
                   "Allows path mask textures to be cached in GPU configs.");
static DEFINE_bool(allPathsVolatile, false,
                   "Causes all GPU paths to be processed as if 'setIsVolatile' had been called.");

static DEFINE_bool(gs, true, "Enables support for geometry shaders (if hw allows).");
static DEFINE_bool(hwtess, false, "Enables support for tessellation shaders (if hw allows.).");

static DEFINE_int(maxTessellationSegments, 0,
                  "Overrides the max number of tessellation segments supported by the caps.");

static DEFINE_bool(alwaysHwTess, false,
        "Always try to use hardware tessellation, regardless of how small a path may be.");

static DEFINE_string(pr, "",
              "Set of enabled gpu path renderers. Defined as a list of: "
              "[~]none [~]dashline [~]ccpr [~]aahairline [~]aaconvex [~]aalinearizing "
              "[~]small [~]tri [~]tess [~]all");

static DEFINE_int(internalSamples, 4, "Number of samples for internal draws that use MSAA.");

static DEFINE_bool(disableDriverCorrectnessWorkarounds, false,
                   "Disables all GPU driver correctness workarounds");

static DEFINE_bool(dontReduceOpsTaskSplitting, false,
                   "Don't reorder tasks to reduce render passes");

static DEFINE_int(gpuResourceCacheLimit, -1,
                  "Maximum number of bytes to use for budgeted GPU resources. "
                  "Default is -1, which means GrResourceCache::kDefaultMaxSize.");

static GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
    if (!strcmp(name, "none")) {
        return GpuPathRenderers::kNone;
    } else if (!strcmp(name, "dashline")) {
        return GpuPathRenderers::kDashLine;
    } else if (!strcmp(name, "ccpr")) {
        return GpuPathRenderers::kCoverageCounting;
    } else if (!strcmp(name, "aahairline")) {
        return GpuPathRenderers::kAAHairline;
    } else if (!strcmp(name, "aaconvex")) {
        return GpuPathRenderers::kAAConvex;
    } else if (!strcmp(name, "aalinearizing")) {
        return GpuPathRenderers::kAALinearizing;
    } else if (!strcmp(name, "small")) {
        return GpuPathRenderers::kSmall;
    } else if (!strcmp(name, "tri")) {
        return GpuPathRenderers::kTriangulating;
    } else if (!strcmp(name, "tess")) {
        return GpuPathRenderers::kTessellation;
    } else if (!strcmp(name, "default")) {
        return GpuPathRenderers::kDefault;
    }
    SK_ABORT("error: unknown named path renderer \"%s\"\n", name);
}

static GpuPathRenderers collect_gpu_path_renderers_from_flags() {
    if (FLAGS_pr.isEmpty()) {
        return GpuPathRenderers::kDefault;
    }

    GpuPathRenderers gpuPathRenderers = ('~' == FLAGS_pr[0][0])
            ? GpuPathRenderers::kDefault
            : GpuPathRenderers::kNone;

    for (int i = 0; i < FLAGS_pr.count(); ++i) {
        const char* name = FLAGS_pr[i];
        if (name[0] == '~') {
            gpuPathRenderers &= ~get_named_pathrenderers_flags(&name[1]);
        } else {
            gpuPathRenderers |= get_named_pathrenderers_flags(name);
        }
    }
    return gpuPathRenderers;
}

void SetCtxOptionsFromCommonFlags(GrContextOptions* ctxOptions) {
    static std::unique_ptr<SkExecutor> gGpuExecutor = (0 != FLAGS_gpuThreads)
        ? SkExecutor::MakeFIFOThreadPool(FLAGS_gpuThreads)
        : nullptr;

    ctxOptions->fExecutor                            = gGpuExecutor.get();
    ctxOptions->fAllowPathMaskCaching                = FLAGS_cachePathMasks;
    ctxOptions->fAllPathsVolatile                    = FLAGS_allPathsVolatile;
    ctxOptions->fSuppressGeometryShaders             = !FLAGS_gs;
    ctxOptions->fEnableExperimentalHardwareTessellation = FLAGS_hwtess;
    ctxOptions->fMaxTessellationSegmentsOverride     = FLAGS_maxTessellationSegments;
    ctxOptions->fAlwaysPreferHardwareTessellation    = FLAGS_alwaysHwTess;
    ctxOptions->fGpuPathRenderers                    = collect_gpu_path_renderers_from_flags();
    ctxOptions->fInternalMultisampleCount            = FLAGS_internalSamples;
    ctxOptions->fDisableDriverCorrectnessWorkarounds = FLAGS_disableDriverCorrectnessWorkarounds;
    ctxOptions->fResourceCacheLimitOverride          = FLAGS_gpuResourceCacheLimit;

    if (FLAGS_dontReduceOpsTaskSplitting) {
        ctxOptions->fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
    } else {
        ctxOptions->fReduceOpsTaskSplitting = GrContextOptions::Enable::kYes;
    }
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <net/inet4>
#include <common.cxx>

using namespace std::string_literals;

extern lest::tests & specification();

CASE("MAC addresses can be compared")
{
  const net::Ethernet::addr host_mac_address {0,240,34,255,45,11};
  const net::Ethernet::addr host_mac_address_hex {0x00,0xf0,0x22,0xff,0x2d,0x0b};
  const net::Ethernet::addr gateway_mac_address {0xb8,0xe8,0x56,0x4a,0x75,0x6e};
  EXPECT_NOT(host_mac_address == gateway_mac_address);
  EXPECT(host_mac_address == host_mac_address_hex);
}

CASE("MAC address string representation prints leading zeros")
{
  const net::Ethernet::addr host_mac_address {0,240,34,255,45,11};
  auto mac_address_string = host_mac_address.str();
  EXPECT_NOT(mac_address_string == "0:f0:22:ff:2d:b");
  EXPECT(mac_address_string == "00:f0:22:ff:2d:0b");
}
<commit_msg>test: Reduced include scope a bit<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <hw/mac_addr.hpp>
#include <common.cxx>

using namespace std::string_literals;

extern lest::tests & specification();

CASE("MAC addresses can be compared")
{
  const hw::MAC_addr host_mac_address {0,240,34,255,45,11};
  const hw::MAC_addr host_mac_address_hex {0x00,0xf0,0x22,0xff,0x2d,0x0b};
  const hw::MAC_addr gateway_mac_address {0xb8,0xe8,0x56,0x4a,0x75,0x6e};
  EXPECT_NOT(host_mac_address == gateway_mac_address);
  EXPECT(host_mac_address == host_mac_address_hex);
}

CASE("MAC address string representation prints leading zeros")
{
  const hw::MAC_addr host_mac_address {0,240,34,255,45,11};
  auto mac_address_string = host_mac_address.str();
  EXPECT_NOT(mac_address_string == "0:f0:22:ff:2d:b");
  EXPECT(mac_address_string == "00:f0:22:ff:2d:0b");
}
<|endoftext|>


<commit_before>//===-- IOStream.cpp --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "IOStream.h"

#if defined(_WIN32)
#include <io.h>
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

#include <fstream>
#include <string>
#include <vector>

using namespace lldb_vscode;

StreamDescriptor::StreamDescriptor() {}

StreamDescriptor::StreamDescriptor(StreamDescriptor &&other) {
  *this = std::move(other);
}

StreamDescriptor::~StreamDescriptor() {
  if (!m_close)
    return;

  if (m_is_socket)
#if defined(_WIN32)
    ::closesocket(m_socket);
#else
    ::close(m_socket);
#endif
  else
    ::close(m_fd);
}

StreamDescriptor &StreamDescriptor::operator=(StreamDescriptor &&other) {
  m_close = other.m_close;
  other.m_close = false;
  m_is_socket = other.m_is_socket;
  if (m_is_socket)
    m_socket = other.m_socket;
  else
    m_fd = other.m_fd;
  return *this;
}

StreamDescriptor StreamDescriptor::from_socket(SOCKET s, bool close) {
  StreamDescriptor sd;
  sd.m_is_socket = true;
  sd.m_socket = s;
  sd.m_close = close;
  return sd;
}

StreamDescriptor StreamDescriptor::from_file(int fd, bool close) {
  StreamDescriptor sd;
  sd.m_is_socket = false;
  sd.m_fd = fd;
  sd.m_close = close;
  return sd;
}

bool OutputStream::write_full(llvm::StringRef str) {
  while (!str.empty()) {
    int bytes_written = 0;
    if (descriptor.m_is_socket)
      bytes_written = ::send(descriptor.m_socket, str.data(), str.size(), 0);
    else
      bytes_written = ::write(descriptor.m_fd, str.data(), str.size());

    if (bytes_written < 0) {
      if (errno == EINTR || errno == EAGAIN)
        continue;
      return false;
    }
    str = str.drop_front(bytes_written);
  }

  return true;
}

bool InputStream::read_full(std::ofstream *log, size_t length,
                            std::string &text) {
  std::string data;
  data.resize(length);

  char *ptr = &data[0];
  while (length != 0) {
    size_t bytes_read = 0;
    if (descriptor.m_is_socket)
      bytes_read = ::recv(descriptor.m_socket, ptr, length, 0);
    else
      bytes_read = ::read(descriptor.m_fd, ptr, length);

    if (bytes_read < 0) {
      int reason = 0;
#if defined(_WIN32)
      if (descriptor.m_is_socket)
        reason = WSAGetLastError();
      else
        reason = errno;
#else
      reason = errno;
      if (reason == EINTR || reason == EAGAIN)
        continue;
#endif

      if (log)
        *log << "Error " << reason << " reading from input file.\n";
      return false;
    }

    assert(bytes_read <= length);
    ptr += bytes_read;
    length -= bytes_read;
  }
  text += data;
  return true;
}

bool InputStream::read_line(std::ofstream *log, std::string &line) {
  line.clear();
  while (true) {
    if (!read_full(log, 1, line))
      return false;

    if (llvm::StringRef(line).endswith("\r\n"))
      break;
  }
  line.erase(line.size() - 2);
  return true;
}

bool InputStream::read_expected(std::ofstream *log, llvm::StringRef expected) {
  std::string result;
  if (!read_full(log, expected.size(), result))
    return false;
  if (expected != result) {
    if (log)
      *log << "Warning: Expected '" << expected.str() << "', got '" << result
           << "\n";
  }
  return true;
}
<commit_msg>[lldb-vscode] Fix warning<commit_after>//===-- IOStream.cpp --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "IOStream.h"

#if defined(_WIN32)
#include <io.h>
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

#include <fstream>
#include <string>
#include <vector>

using namespace lldb_vscode;

StreamDescriptor::StreamDescriptor() {}

StreamDescriptor::StreamDescriptor(StreamDescriptor &&other) {
  *this = std::move(other);
}

StreamDescriptor::~StreamDescriptor() {
  if (!m_close)
    return;

  if (m_is_socket)
#if defined(_WIN32)
    ::closesocket(m_socket);
#else
    ::close(m_socket);
#endif
  else
    ::close(m_fd);
}

StreamDescriptor &StreamDescriptor::operator=(StreamDescriptor &&other) {
  m_close = other.m_close;
  other.m_close = false;
  m_is_socket = other.m_is_socket;
  if (m_is_socket)
    m_socket = other.m_socket;
  else
    m_fd = other.m_fd;
  return *this;
}

StreamDescriptor StreamDescriptor::from_socket(SOCKET s, bool close) {
  StreamDescriptor sd;
  sd.m_is_socket = true;
  sd.m_socket = s;
  sd.m_close = close;
  return sd;
}

StreamDescriptor StreamDescriptor::from_file(int fd, bool close) {
  StreamDescriptor sd;
  sd.m_is_socket = false;
  sd.m_fd = fd;
  sd.m_close = close;
  return sd;
}

bool OutputStream::write_full(llvm::StringRef str) {
  while (!str.empty()) {
    int bytes_written = 0;
    if (descriptor.m_is_socket)
      bytes_written = ::send(descriptor.m_socket, str.data(), str.size(), 0);
    else
      bytes_written = ::write(descriptor.m_fd, str.data(), str.size());

    if (bytes_written < 0) {
      if (errno == EINTR || errno == EAGAIN)
        continue;
      return false;
    }
    str = str.drop_front(bytes_written);
  }

  return true;
}

bool InputStream::read_full(std::ofstream *log, size_t length,
                            std::string &text) {
  std::string data;
  data.resize(length);

  char *ptr = &data[0];
  while (length != 0) {
    int bytes_read = 0;
    if (descriptor.m_is_socket)
      bytes_read = ::recv(descriptor.m_socket, ptr, length, 0);
    else
      bytes_read = ::read(descriptor.m_fd, ptr, length);

    if (bytes_read < 0) {
      int reason = 0;
#if defined(_WIN32)
      if (descriptor.m_is_socket)
        reason = WSAGetLastError();
      else
        reason = errno;
#else
      reason = errno;
      if (reason == EINTR || reason == EAGAIN)
        continue;
#endif

      if (log)
        *log << "Error " << reason << " reading from input file.\n";
      return false;
    }

    assert(bytes_read >= 0 && (size_t)bytes_read <= length);
    ptr += bytes_read;
    length -= bytes_read;
  }
  text += data;
  return true;
}

bool InputStream::read_line(std::ofstream *log, std::string &line) {
  line.clear();
  while (true) {
    if (!read_full(log, 1, line))
      return false;

    if (llvm::StringRef(line).endswith("\r\n"))
      break;
  }
  line.erase(line.size() - 2);
  return true;
}

bool InputStream::read_expected(std::ofstream *log, llvm::StringRef expected) {
  std::string result;
  if (!read_full(log, expected.size(), result))
    return false;
  if (expected != result) {
    if (log)
      *log << "Warning: Expected '" << expected.str() << "', got '" << result
           << "\n";
  }
  return true;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    wrap_itkImageSource.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkImage.h"
#include "itkImageToImageFilter.h"

#ifdef CABLE_CONFIGURATION
#include "itkCSwigImages.h"
#include "itkCSwigMacros.h"

namespace _cable_
{
  const char* const group = ITK_WRAP_GROUP(itkImageSource);
  namespace wrappers
  {
    ITK_WRAP_OBJECT1(ImageSource, image::F2 , itkImageSourceF2 );
    ITK_WRAP_OBJECT1(ImageSource, image::D2 , itkImageSourceD2 );
    ITK_WRAP_OBJECT1(ImageSource, image::UC2, itkImageSourceUC2);
    ITK_WRAP_OBJECT1(ImageSource, image::US2, itkImageSourceUS2);
    ITK_WRAP_OBJECT1(ImageSource, image::UI2, itkImageSourceUI2);
    ITK_WRAP_OBJECT1(ImageSource, image::UL2, itkImageSourceUL2);
    ITK_WRAP_OBJECT1(ImageSource, image::SC2, itkImageSourceSC2);
    ITK_WRAP_OBJECT1(ImageSource, image::SS2, itkImageSourceSS2);
    ITK_WRAP_OBJECT1(ImageSource, image::SI2, itkImageSourceSI2);

    ITK_WRAP_OBJECT1(ImageSource, image::F3 , itkImageSourceF3 );
    ITK_WRAP_OBJECT1(ImageSource, image::D3 , itkImageSourceD3 );
    ITK_WRAP_OBJECT1(ImageSource, image::UC3, itkImageSourceUC3);
    ITK_WRAP_OBJECT1(ImageSource, image::US3, itkImageSourceUS3);
    ITK_WRAP_OBJECT1(ImageSource, image::UI3, itkImageSourceUI3);
    ITK_WRAP_OBJECT1(ImageSource, image::UL3, itkImageSourceUL3);
    ITK_WRAP_OBJECT1(ImageSource, image::SC3, itkImageSourceSC3);
    ITK_WRAP_OBJECT1(ImageSource, image::SS3, itkImageSourceSS3);
    ITK_WRAP_OBJECT1(ImageSource, image::SI3, itkImageSourceSI3);
  }
}
#endif
<commit_msg>ENH: Adding wrapping for output images of Vector and CovariantVectors 2D.3D.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    wrap_itkImageSource.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkImage.h"
#include "itkImageToImageFilter.h"

#ifdef CABLE_CONFIGURATION
#include "itkCSwigImages.h"
#include "itkCSwigMacros.h"

namespace _cable_
{
  const char* const group = ITK_WRAP_GROUP(itkImageSource);
  namespace wrappers
  {
    ITK_WRAP_OBJECT1(ImageSource, image::F2 , itkImageSourceF2 );
    ITK_WRAP_OBJECT1(ImageSource, image::D2 , itkImageSourceD2 );
    ITK_WRAP_OBJECT1(ImageSource, image::UC2, itkImageSourceUC2);
    ITK_WRAP_OBJECT1(ImageSource, image::US2, itkImageSourceUS2);
    ITK_WRAP_OBJECT1(ImageSource, image::UI2, itkImageSourceUI2);
    ITK_WRAP_OBJECT1(ImageSource, image::UL2, itkImageSourceUL2);
    ITK_WRAP_OBJECT1(ImageSource, image::SC2, itkImageSourceSC2);
    ITK_WRAP_OBJECT1(ImageSource, image::SS2, itkImageSourceSS2);
    ITK_WRAP_OBJECT1(ImageSource, image::SI2, itkImageSourceSI2);
    ITK_WRAP_OBJECT1(ImageSource, image::VF2 , itkImageSourceVF2 );
    ITK_WRAP_OBJECT1(ImageSource, image::CVF2 , itkImageSourceCVF2 );

    ITK_WRAP_OBJECT1(ImageSource, image::F3 , itkImageSourceF3 );
    ITK_WRAP_OBJECT1(ImageSource, image::D3 , itkImageSourceD3 );
    ITK_WRAP_OBJECT1(ImageSource, image::UC3, itkImageSourceUC3);
    ITK_WRAP_OBJECT1(ImageSource, image::US3, itkImageSourceUS3);
    ITK_WRAP_OBJECT1(ImageSource, image::UI3, itkImageSourceUI3);
    ITK_WRAP_OBJECT1(ImageSource, image::UL3, itkImageSourceUL3);
    ITK_WRAP_OBJECT1(ImageSource, image::SC3, itkImageSourceSC3);
    ITK_WRAP_OBJECT1(ImageSource, image::SS3, itkImageSourceSS3);
    ITK_WRAP_OBJECT1(ImageSource, image::SI3, itkImageSourceSI3);
    ITK_WRAP_OBJECT1(ImageSource, image::VF3 , itkImageSourceVF3 );
    ITK_WRAP_OBJECT1(ImageSource, image::CVF3 , itkImageSourceCVF3 );
  }
}
#endif
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <iostream>
#include <cstring>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "clientCommands.cpp"

void closeSocket(int atmSocket) {
	printf("Closing \n");
	fflush(stdout);
	close(atmSocket);
	exit(1);
}

int main(int argc, char *argv[]){

  // Check for arguments (port number is provided)
  if(argc != 2){
		printf("Run ./ATMClient <proxy-port-number>\n");
		return -1;
	}

  //socket setup
	unsigned int proxyPortNo = atoi(argv[1]);
	int atmSocket = socket(AF_INET, SOCK_STREAM, 0);
	if(atmSocket == -1){
		printf("Did not connect to socket\n");
		return -1;
	}

	//Close sock on Ctrl-C
	signal(SIGINT, closeSocket);

  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(proxyPortNo);
  addr.sin_addr.s_addr = INADDR_ANY;

  if(0 != connect(atmSocket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))){
    printf("Did not connect to socket\n");
    return -1;
  }

	// Initial message

	int messageNumber = 1;

	// TODO: implement message number
	// std::string number= std::to_string(messageNumber);
	// messageNumber++;

	char mess[256];
	strcpy(mess, "init");
	int n = write(atmSocket, mess, strlen(mess)+1);
	if (n < 0) error("ERROR something is wrong");
	char buf[256];
	n = read(atmSocket,buf,255);
  if (n < 0) error("ERROR reading from socket");
  //input loop
  bool loggedin = false;
	std::string sessionKey;
	std::string input;

	printf("atm ~ : ");

  while(1){

		getline(std::cin, input);

    // fgets(buf, 255, stdin);
		// buf[strlen(buf)-1] = '\0';	//trim off trailing newline
    // std::string input(buf);
    int index = 0;
		if (input.length() == 0) continue;
    std::string command = advanceCommand(input, index);

    if(command.compare("exit") == 0){
      closeSocket(atmSocket);
    }

    if(loggedin){
      // Login in
      if(command.compare("balance") == 0){
        advanceSpaces(input, index);
        std::cout << "Obtaining Balance..." << std::endl;
        balance(sessionKey, atmSocket);
      }

      else if(command.compare("withdraw") == 0){
        advanceSpaces(input, index);
        std::string amountString = advanceCommand(input, index);
        float amount = atof(amountString.c_str());
        std::cout << amount << std::endl;
      }

      else if(command.compare("transfer") == 0){
        advanceSpaces(input, index);
        std::string amountString = advanceCommand(input, index);
        float amount = atof(amountString.c_str());
        advanceSpaces(input, index);
        std::string username = advanceCommand(input, index);
        std::cout << username << std::endl;
      }

      else if(command.compare("logout") == 0){
        advanceSpaces(input, index);
				closeSocket(atmSocket);
        std::cout << "Logging Out..." << std::endl;
        exit(0);
      }
      else{
        std::cout << "You suck man" << std::endl;
      }
    }

    else{
      // Login in
      if(command.compare("login") == 0){
        advanceSpaces(input, index);
        std::string username = advanceCommand(input, index);
        std::cout << username << std::endl;
        std::string ans = login(username, atmSocket);
				if(ans != "broken"){
					sessionKey = ans;
					loggedin = true;
				}
      }
    }

		printf("atm ~ : ");

  }

  //cleanup
  close(atmSocket);
  return 0;
  }
<commit_msg> withdraw<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <iostream>
#include <cstring>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "clientCommands.cpp"

void closeSocket(int atmSocket) {
	printf("Closing \n");
	fflush(stdout);
	close(atmSocket);
	exit(1);
}

int main(int argc, char *argv[]){

  // Check for arguments (port number is provided)
  if(argc != 2){
		printf("Run ./ATMClient <proxy-port-number>\n");
		return -1;
	}

  //socket setup
	unsigned int proxyPortNo = atoi(argv[1]);
	int atmSocket = socket(AF_INET, SOCK_STREAM, 0);
	if(atmSocket == -1){
		printf("Did not connect to socket\n");
		return -1;
	}

	//Close sock on Ctrl-C
	signal(SIGINT, closeSocket);

  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(proxyPortNo);
  addr.sin_addr.s_addr = INADDR_ANY;

  if(0 != connect(atmSocket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))){
    printf("Did not connect to socket\n");
    return -1;
  }

	// Initial message

	int messageNumber = 1;

	// TODO: implement message number
	// std::string number= std::to_string(messageNumber);
	// messageNumber++;

	char mess[256];
	strcpy(mess, "init");
	int n = write(atmSocket, mess, strlen(mess)+1);
	if (n < 0) error("ERROR something is wrong");
	char buf[256];
	n = read(atmSocket,buf,255);
  if (n < 0) error("ERROR reading from socket");
  //input loop
  bool loggedin = false;
	std::string sessionKey;
	std::string input;

	printf("atm ~ : ");

  while(1){

		getline(std::cin, input);

    // fgets(buf, 255, stdin);
		// buf[strlen(buf)-1] = '\0';	//trim off trailing newline
    // std::string input(buf);
    int index = 0;
		if (input.length() == 0) continue;
    std::string command = advanceCommand(input, index);

    if(command.compare("exit") == 0){
      closeSocket(atmSocket);
    }

    if(loggedin){
      // Login in
      if(command.compare("balance") == 0){
        advanceSpaces(input, index);
        std::cout << "Obtaining Balance..." << std::endl;
        balance(sessionKey, atmSocket);
      }

      else if(command.compare("withdraw") == 0){
        advanceSpaces(input, index);
        std::string amountString = advanceCommand(input, index);
        float amount = atof(amountString.c_str());
				withdraw(sessionKey, amountString, atmSocket){
      }

      else if(command.compare("transfer") == 0){
        advanceSpaces(input, index);
        std::string amountString = advanceCommand(input, index);
        float amount = atof(amountString.c_str());
        advanceSpaces(input, index);
        std::string username = advanceCommand(input, index);
        std::cout << username << std::endl;
      }

      else if(command.compare("logout") == 0){
        advanceSpaces(input, index);
				closeSocket(atmSocket);
        std::cout << "Logging Out..." << std::endl;
        exit(0);
      }
      else{
        std::cout << "You suck man" << std::endl;
      }
    }

    else{
      // Login in
      if(command.compare("login") == 0){
        advanceSpaces(input, index);
        std::string username = advanceCommand(input, index);
        std::cout << username << std::endl;
        std::string ans = login(username, atmSocket);
				if(ans != "broken"){
					sessionKey = ans;
					loggedin = true;
				}
      }
    }

		printf("atm ~ : ");

  }

  //cleanup
  close(atmSocket);
  return 0;
  }
<|endoftext|>


<commit_before><commit_msg>ByteString->rtl::OString<commit_after><|endoftext|>


<commit_before><commit_msg>WaE: unreferenced formal parameter<commit_after><|endoftext|>


<commit_before>/*
 * ApiClient.cpp
 */

#include "ApiClient.h"

ApiClient::ApiClient()
{
	request_buffer.reserve(BUFF_SIZE);
}

unsigned int ApiClient::request()
{
	return 0;
	//return runShellCommand(request_buffer);
}

unsigned int ApiClient::get(const __FlashStringHelper *url)
{
	return request();
}

unsigned int ApiClient::get(const String &url)
{
	return request();
}

unsigned int ApiClient::get(const char *url)
{
	return request();
}

unsigned int ApiClient::post(const __FlashStringHelper *url, const __FlashStringHelper *data)
{
	request_buffer = F("curl -X POST ");
	request_buffer += F("-H \"Authorization: ");
	addAuthorizationHeader();
	request_buffer += F("\" ");
	request_buffer += F("-H \"Content-Type: ");
	addContentTypeHeader();
	request_buffer += F("\" ");
	request_buffer += F("-d '");
	request_buffer += data;
	request_buffer += F("' ");
	request_buffer += url;
	return request();
}

unsigned int ApiClient::post(const String &url, const String &data)
{
	request_buffer = F("curl -X POST ");
	request_buffer += F("-H \"Authorization: ");
	addAuthorizationHeader();
	request_buffer += F("\" ");
	request_buffer += F("-H \"Content-Type: ");
	addContentTypeHeader();
	request_buffer += F("\" ");
	request_buffer += F("-d '");
	request_buffer += data;
	request_buffer += F("' ");
	request_buffer += url;
	return request();
}

unsigned int ApiClient::post(const char *url, const char *data)
{
	request_buffer = F("curl -X POST ");
	request_buffer += F("-H \"Authorization: ");
	addAuthorizationHeader();
	request_buffer += F("\" ");
	request_buffer += F("-H \"Content-Type: ");
	addContentTypeHeader();
	request_buffer += F("\" ");
	request_buffer += F("-d '");
	request_buffer += data;
	request_buffer += F("' ");
	request_buffer += url;
	return request();
}

void ApiClient::setAuthorizationHeader(StringPointer auth_header)
{
	this->auth_header = auth_header;
}

void ApiClient::setAuthorizationHeader(const __FlashStringHelper *auth_header)
{
	this->auth_header.u.flashstring_ptr = auth_header;
	this->auth_header.type = POINTER_UNION_TYPE_FLASHSTRING;
}

void ApiClient::setAuthorizationHeader(const String *auth_header)
{
	this->auth_header.u.string_ptr = auth_header;
	this->auth_header.type = POINTER_UNION_TYPE_STRING;
}

void ApiClient::setAuthorizationHeader(const char *auth_header)
{
	this->auth_header.u.char_ptr = auth_header;
	this->auth_header.type = POINTER_UNION_TYPE_CHAR;
}

void ApiClient::getAuthorizationHeader()
{
	switch(auth_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			Serial.println(auth_header.u.flashstring_ptr);
			break;
		case POINTER_UNION_TYPE_STRING:
			Serial.println(*auth_header.u.string_ptr);
			break;
		case POINTER_UNION_TYPE_CHAR:
			Serial.println(auth_header.u.char_ptr);
			break;
		default:
			break;
	}
}

void ApiClient::addAuthorizationHeader()
{
	switch(auth_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			request_buffer += auth_header.u.flashstring_ptr;
			break;
		case POINTER_UNION_TYPE_STRING:
			request_buffer += *auth_header.u.string_ptr;
			break;
		case POINTER_UNION_TYPE_CHAR:
			request_buffer += auth_header.u.char_ptr;
			break;
		default:
			break;
	}
}

void ApiClient::setContentTypeHeader(const __FlashStringHelper *contenttype_header)
{
	this->contenttype_header.u.flashstring_ptr = contenttype_header;
	this->contenttype_header.type = POINTER_UNION_TYPE_FLASHSTRING;
}

void ApiClient::setContentTypeHeader(const String *contenttype_header)
{
	this->contenttype_header.u.string_ptr = contenttype_header;
	this->contenttype_header.type = POINTER_UNION_TYPE_STRING;
}

void ApiClient::setContentTypeHeader(const char *contenttype_header)
{
	this->contenttype_header.u.char_ptr = contenttype_header;
	this->contenttype_header.type = POINTER_UNION_TYPE_CHAR;
}

void ApiClient::getContentTypeHeader()
{
	switch(contenttype_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			Serial.println(contenttype_header.u.flashstring_ptr);
			break;
		case POINTER_UNION_TYPE_STRING:
			Serial.println(*contenttype_header.u.string_ptr);
			break;
		case POINTER_UNION_TYPE_CHAR:
			Serial.println(contenttype_header.u.char_ptr);
			break;
		default:
			break;
	}
}

void ApiClient::addContentTypeHeader()
{
	switch(contenttype_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			request_buffer += contenttype_header.u.flashstring_ptr;
			break;
		case POINTER_UNION_TYPE_STRING:
			request_buffer += *contenttype_header.u.string_ptr;
			break;
		case POINTER_UNION_TYPE_CHAR:
			request_buffer += contenttype_header.u.char_ptr;
			break;
		default:
			break;
	}
}

void ApiClient::setUserAgentHeader(const __FlashStringHelper *useragent_header)
{
	this->useragent_header.u.flashstring_ptr = useragent_header;
	this->useragent_header.type = POINTER_UNION_TYPE_FLASHSTRING;
}

void ApiClient::setUserAgentHeader(const String *useragent_header)
{
	this->useragent_header.u.string_ptr = useragent_header;
	this->useragent_header.type = POINTER_UNION_TYPE_STRING;
}

void ApiClient::setUserAgentHeader(const char *useragent_header)
{
	this->useragent_header.u.char_ptr = useragent_header;
	this->useragent_header.type = POINTER_UNION_TYPE_CHAR;
}

void ApiClient::getUserAgentHeader()
{
	switch(useragent_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			Serial.println(useragent_header.u.flashstring_ptr);
			break;
		case POINTER_UNION_TYPE_STRING:
			Serial.println(*useragent_header.u.string_ptr);
			break;
		case POINTER_UNION_TYPE_CHAR:
			Serial.println(useragent_header.u.char_ptr);
			break;
		default:
			break;
	}
}

void ApiClient::addUserAgentHeader()
{
	switch(useragent_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			request_buffer += useragent_header.u.flashstring_ptr;
			break;
		case POINTER_UNION_TYPE_STRING:
			request_buffer += *useragent_header.u.string_ptr;
			break;
		case POINTER_UNION_TYPE_CHAR:
			request_buffer += useragent_header.u.char_ptr;
			break;
		default:
			break;
	}
}

void ApiClient::printRequest()
{
	Serial.println(request_buffer);
}

<commit_msg>Enabled posting to the API.<commit_after>/*
 * ApiClient.cpp
 */

#include "ApiClient.h"

ApiClient::ApiClient()
{
	request_buffer.reserve(BUFF_SIZE);
}

unsigned int ApiClient::request()
{
	return runShellCommand(request_buffer);
}

unsigned int ApiClient::get(const __FlashStringHelper *url)
{
	return request();
}

unsigned int ApiClient::get(const String &url)
{
	return request();
}

unsigned int ApiClient::get(const char *url)
{
	return request();
}

unsigned int ApiClient::post(const __FlashStringHelper *url, const __FlashStringHelper *data)
{
	request_buffer = F("curl -X POST ");
	request_buffer += F("-H \"Authorization: ");
	addAuthorizationHeader();
	request_buffer += F("\" ");
	request_buffer += F("-H \"Content-Type: ");
	addContentTypeHeader();
	request_buffer += F("\" ");
	request_buffer += F("-d '");
	request_buffer += data;
	request_buffer += F("' ");
	request_buffer += url;
	return request();
}

unsigned int ApiClient::post(const String &url, const String &data)
{
	request_buffer = F("curl -X POST ");
	request_buffer += F("-H \"Authorization: ");
	addAuthorizationHeader();
	request_buffer += F("\" ");
	request_buffer += F("-H \"Content-Type: ");
	addContentTypeHeader();
	request_buffer += F("\" ");
	request_buffer += F("-d '");
	request_buffer += data;
	request_buffer += F("' ");
	request_buffer += url;
	return request();
}

unsigned int ApiClient::post(const char *url, const char *data)
{
	request_buffer = F("curl -X POST ");
	request_buffer += F("-H \"Authorization: ");
	addAuthorizationHeader();
	request_buffer += F("\" ");
	request_buffer += F("-H \"Content-Type: ");
	addContentTypeHeader();
	request_buffer += F("\" ");
	request_buffer += F("-d '");
	request_buffer += data;
	request_buffer += F("' ");
	request_buffer += url;
	return request();
}

void ApiClient::setAuthorizationHeader(StringPointer auth_header)
{
	this->auth_header = auth_header;
}

void ApiClient::setAuthorizationHeader(const __FlashStringHelper *auth_header)
{
	this->auth_header.u.flashstring_ptr = auth_header;
	this->auth_header.type = POINTER_UNION_TYPE_FLASHSTRING;
}

void ApiClient::setAuthorizationHeader(const String *auth_header)
{
	this->auth_header.u.string_ptr = auth_header;
	this->auth_header.type = POINTER_UNION_TYPE_STRING;
}

void ApiClient::setAuthorizationHeader(const char *auth_header)
{
	this->auth_header.u.char_ptr = auth_header;
	this->auth_header.type = POINTER_UNION_TYPE_CHAR;
}

void ApiClient::getAuthorizationHeader()
{
	switch(auth_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			Serial.println(auth_header.u.flashstring_ptr);
			break;
		case POINTER_UNION_TYPE_STRING:
			Serial.println(*auth_header.u.string_ptr);
			break;
		case POINTER_UNION_TYPE_CHAR:
			Serial.println(auth_header.u.char_ptr);
			break;
		default:
			break;
	}
}

void ApiClient::addAuthorizationHeader()
{
	switch(auth_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			request_buffer += auth_header.u.flashstring_ptr;
			break;
		case POINTER_UNION_TYPE_STRING:
			request_buffer += *auth_header.u.string_ptr;
			break;
		case POINTER_UNION_TYPE_CHAR:
			request_buffer += auth_header.u.char_ptr;
			break;
		default:
			break;
	}
}

void ApiClient::setContentTypeHeader(const __FlashStringHelper *contenttype_header)
{
	this->contenttype_header.u.flashstring_ptr = contenttype_header;
	this->contenttype_header.type = POINTER_UNION_TYPE_FLASHSTRING;
}

void ApiClient::setContentTypeHeader(const String *contenttype_header)
{
	this->contenttype_header.u.string_ptr = contenttype_header;
	this->contenttype_header.type = POINTER_UNION_TYPE_STRING;
}

void ApiClient::setContentTypeHeader(const char *contenttype_header)
{
	this->contenttype_header.u.char_ptr = contenttype_header;
	this->contenttype_header.type = POINTER_UNION_TYPE_CHAR;
}

void ApiClient::getContentTypeHeader()
{
	switch(contenttype_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			Serial.println(contenttype_header.u.flashstring_ptr);
			break;
		case POINTER_UNION_TYPE_STRING:
			Serial.println(*contenttype_header.u.string_ptr);
			break;
		case POINTER_UNION_TYPE_CHAR:
			Serial.println(contenttype_header.u.char_ptr);
			break;
		default:
			break;
	}
}

void ApiClient::addContentTypeHeader()
{
	switch(contenttype_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			request_buffer += contenttype_header.u.flashstring_ptr;
			break;
		case POINTER_UNION_TYPE_STRING:
			request_buffer += *contenttype_header.u.string_ptr;
			break;
		case POINTER_UNION_TYPE_CHAR:
			request_buffer += contenttype_header.u.char_ptr;
			break;
		default:
			break;
	}
}

void ApiClient::setUserAgentHeader(const __FlashStringHelper *useragent_header)
{
	this->useragent_header.u.flashstring_ptr = useragent_header;
	this->useragent_header.type = POINTER_UNION_TYPE_FLASHSTRING;
}

void ApiClient::setUserAgentHeader(const String *useragent_header)
{
	this->useragent_header.u.string_ptr = useragent_header;
	this->useragent_header.type = POINTER_UNION_TYPE_STRING;
}

void ApiClient::setUserAgentHeader(const char *useragent_header)
{
	this->useragent_header.u.char_ptr = useragent_header;
	this->useragent_header.type = POINTER_UNION_TYPE_CHAR;
}

void ApiClient::getUserAgentHeader()
{
	switch(useragent_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			Serial.println(useragent_header.u.flashstring_ptr);
			break;
		case POINTER_UNION_TYPE_STRING:
			Serial.println(*useragent_header.u.string_ptr);
			break;
		case POINTER_UNION_TYPE_CHAR:
			Serial.println(useragent_header.u.char_ptr);
			break;
		default:
			break;
	}
}

void ApiClient::addUserAgentHeader()
{
	switch(useragent_header.type) {
		case POINTER_UNION_TYPE_FLASHSTRING:
			request_buffer += useragent_header.u.flashstring_ptr;
			break;
		case POINTER_UNION_TYPE_STRING:
			request_buffer += *useragent_header.u.string_ptr;
			break;
		case POINTER_UNION_TYPE_CHAR:
			request_buffer += useragent_header.u.char_ptr;
			break;
		default:
			break;
	}
}

void ApiClient::printRequest()
{
	Serial.println(request_buffer);
}

<|endoftext|>