<commit_before>// Time:  O(n + c * n * 2^c), try all the possible game strings,
//                            and each string would have c choices to become the next string
// Space: O(n * 2^c), keep all the possible game strings

// hash solution.
class Solution {
public:
    bool canWin(string s) {
        if (!lookup_.count(s)) {
            const int n = s.length();
            bool is_win = false;
            for (int i = 0; !is_win && i < n - 1; ++i) {
                if (s[i] == '+') {
                    for (; !is_win && i < n - 1 && s[i + 1] == '+'; ++i) {
                        s[i] = s[i + 1] = '-';
                        is_win = !canWin(s);
                        s[i] = s[i + 1] = '+';
                        lookup_[s] = is_win;
                    }
                }
            }
        }
        return lookup_[s];
    }
private:
    unordered_map<string, bool> lookup_;
};

// Time:  O(n * c!), n is length of string, c is count of "++"
// Space: O(c), recursion would be called at most c in depth.
//              Besides, no extra space in each depth for the modified string.
class Solution2 {
public:
    bool canWin(string s) {
        const int n = s.length();
        bool is_win = false;
        for (int i = 0; !is_win && i < n - 1; ++i) {  // O(n) time
            if (s[i] == '+') {
                for (; !is_win && i < n - 1 && s[i + 1] == '+'; ++i) {  // O(c) time
                    s[i] = s[i + 1] = '-';
                    // t(n, c) = c * t(n, c - 1) + n = ... = c! * t(n, 0) + n * c! * (1/0! + 1/1! + ... 1/c!)
                    // = n * c! + n * c! * O(e) = O(n * c!)
                    is_win = !canWin(s);
                     s[i] = s[i + 1] = '+';
                }
            }
        }
        return is_win;
    }
};
<commit_msg>Update flip-game-ii.cpp<commit_after>// Time:  O(n + c^3 * 2^c * logc)
// Space: O(c * 2^c)

// hash solution.
class Solution {
public:
    struct multiset_hash {
        std::size_t operator() (const multiset<int>& set) const {
            string set_string;
            for (const auto& i : set) {
                set_string.append(to_string(i) + " ");
            }
            return hash<string>()(set_string);
        }
    };

    bool canWin(string s) {
        const int n = s.length();
        multiset<int> consecutives;
        for (int i = 0; i < n - 1; ++i) {  // O(n) time
            if (s[i] == '+') {
                int c = 1;
                for (; i < n - 1 && s[i + 1] == '+'; ++i, ++c);
                if (c >= 2) {
                    consecutives.emplace(c);
                }
            }
        }
        return canWinHelper(consecutives);
    }

private:
    bool canWinHelper(const multiset<int>& consecutives) {
        if (!lookup_.count(consecutives)) {
            bool is_win = false;
            for (auto it = consecutives.cbegin(); !is_win && it != consecutives.cend(); ++it) {
                const int c = *it;
                multiset<int> next_consecutives(consecutives);
                next_consecutives.erase(next_consecutives.find(c));
                for (int i = 0; !is_win && i < c - 1; ++i) {
                    if (i >= 2) {
                        next_consecutives.emplace(i);
                    }
                    if (c - 2 - i >= 2) {
                        next_consecutives.emplace(c - 2 - i);
                    }
                    is_win = !canWinHelper(next_consecutives);
                    if (i >= 2) {
                        next_consecutives.erase(next_consecutives.find(i));
                    }
                    if (c - 2 - i >= 2) {
                        next_consecutives.erase(next_consecutives.find(c - 2 - i));
                    }
                    lookup_[consecutives] = is_win;
                }
            }
        }
        return lookup_[consecutives];
    }
    unordered_map<multiset<int>, bool, multiset_hash> lookup_;
};

// Time:  O(n + c * n * 2^c), try all the possible game strings,
//                            and each string would have c choices to become the next string
// Space: O(n * 2^c), keep all the possible game strings
// hash solution.
class Solution2 {
public:
    bool canWin(string s) {
        if (!lookup_.count(s)) {
            const int n = s.length();
            bool is_win = false;
            for (int i = 0; !is_win && i < n - 1; ++i) {
                if (s[i] == '+') {
                    for (; !is_win && i < n - 1 && s[i + 1] == '+'; ++i) {
                        s[i] = s[i + 1] = '-';
                        is_win = !canWin(s);
                        s[i] = s[i + 1] = '+';
                        lookup_[s] = is_win;
                    }
                }
            }
        }
        return lookup_[s];
    }
private:
    unordered_map<string, bool> lookup_;
};

// Time:  O(n * c!), n is length of string, c is count of "++"
// Space: O(c), recursion would be called at most c in depth.
//              Besides, no extra space in each depth for the modified string.
class Solution3 {
public:
    bool canWin(string s) {
        const int n = s.length();
        bool is_win = false;
        for (int i = 0; !is_win && i < n - 1; ++i) {  // O(n) time
            if (s[i] == '+') {
                for (; !is_win && i < n - 1 && s[i + 1] == '+'; ++i) {  // O(c) time
                    s[i] = s[i + 1] = '-';
                    // t(n, c) = c * t(n, c - 1) + n = ... = c! * t(n, 0) + n * c! * (1/0! + 1/1! + ... 1/c!)
                    // = n * c! + n * c! * O(e) = O(n * c!)
                    is_win = !canWin(s);
                     s[i] = s[i + 1] = '+';
                }
            }
        }
        return is_win;
    }
};
<|endoftext|>


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

#include "ppapi/cpp/var.h"

#include <string.h>

#include <algorithm>

#include "ppapi/c/pp_var.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/cpp/common.h"
#include "ppapi/cpp/logging.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"

// Defining snprintf
#include <stdio.h>
#if defined(_MSC_VER)
#  define snprintf _snprintf_s
#endif

namespace {

DeviceFuncs<PPB_Var_Deprecated> ppb_var_f(PPB_VAR_DEPRECATED_INTERFACE);

// Technically you can call AddRef and Release on any Var, but it may involve
// cross-process calls depending on the plugin. This is an optimization so we
// only do refcounting on the necessary objects.
inline bool NeedsRefcounting(const PP_Var& var) {
  return var.type == PP_VARTYPE_STRING || var.type == PP_VARTYPE_OBJECT;
}

}  // namespace

namespace pp {

using namespace deprecated;

Var::Var() {
  var_.type = PP_VARTYPE_UNDEFINED;
  needs_release_ = false;
}

Var::Var(Null) {
  var_.type = PP_VARTYPE_NULL;
  needs_release_ = false;
}

Var::Var(bool b) {
  var_.type = PP_VARTYPE_BOOL;
  var_.value.as_bool = BoolToPPBool(b);
  needs_release_ = false;
}

Var::Var(int32_t i) {
  var_.type = PP_VARTYPE_INT32;
  var_.value.as_int = i;
  needs_release_ = false;
}

Var::Var(double d) {
  var_.type = PP_VARTYPE_DOUBLE;
  var_.value.as_double = d;
  needs_release_ = false;
}

Var::Var(const char* utf8_str) {
  if (ppb_var_f) {
    uint32_t len = utf8_str ? static_cast<uint32_t>(strlen(utf8_str)) : 0;
    var_ = ppb_var_f->VarFromUtf8(Module::Get()->pp_module(), utf8_str, len);
  } else {
    var_.type = PP_VARTYPE_NULL;
  }
  needs_release_ = (var_.type == PP_VARTYPE_STRING);
}

Var::Var(const std::string& utf8_str) {
  if (ppb_var_f) {
    var_ = ppb_var_f->VarFromUtf8(Module::Get()->pp_module(),
                                  utf8_str.c_str(),
                                  static_cast<uint32_t>(utf8_str.size()));
  } else {
    var_.type = PP_VARTYPE_NULL;
  }
  needs_release_ = (var_.type == PP_VARTYPE_STRING);
}

Var::Var(ScriptableObject* object) {
  if (ppb_var_f) {
    var_ = ppb_var_f->CreateObject(Module::Get()->pp_module(),
                                   object->GetClass(), object);
    needs_release_ = true;
  } else {
    var_.type = PP_VARTYPE_NULL;
    needs_release_ = false;
  }
}

Var::Var(const Var& other) {
  var_ = other.var_;
  if (NeedsRefcounting(var_)) {
    if (ppb_var_f) {
      needs_release_ = true;
      ppb_var_f->AddRef(var_);
    } else {
      var_.type = PP_VARTYPE_NULL;
      needs_release_ = false;
    }
  } else {
    needs_release_ = false;
  }
}

Var::~Var() {
  if (needs_release_ && ppb_var_f)
    ppb_var_f->Release(var_);
}

Var& Var::operator=(const Var& other) {
  if (needs_release_ && ppb_var_f)
    ppb_var_f->Release(var_);
  var_ = other.var_;
  if (NeedsRefcounting(var_)) {
    if (ppb_var_f) {
      needs_release_ = true;
      ppb_var_f->AddRef(var_);
    } else {
      var_.type = PP_VARTYPE_NULL;
      needs_release_ = false;
    }
  } else {
    needs_release_ = false;
  }
  return *this;
}

bool Var::operator==(const Var& other) const {
  if (var_.type != other.var_.type)
    return false;
  switch (var_.type) {
    case PP_VARTYPE_UNDEFINED:
    case PP_VARTYPE_NULL:
      return true;
    case PP_VARTYPE_BOOL:
      return AsBool() == other.AsBool();
    case PP_VARTYPE_INT32:
      return AsInt() == other.AsInt();
    case PP_VARTYPE_DOUBLE:
      return AsDouble() == other.AsDouble();
    case PP_VARTYPE_STRING:
      if (var_.value.as_id == other.var_.value.as_id)
        return true;
      return AsString() == other.AsString();
    // TODO(neb): Document that this is === and not ==, unlike strings.
    case PP_VARTYPE_OBJECT:
      return var_.value.as_id == other.var_.value.as_id;
    default:
      return false;
  }
}

bool Var::AsBool() const {
  if (!is_bool()) {
    PP_NOTREACHED();
    return false;
  }
  return PPBoolToBool(var_.value.as_bool);
}

int32_t Var::AsInt() const {
  if (is_int())
    return var_.value.as_int;
  if (is_double())
    return static_cast<int>(var_.value.as_double);
  PP_NOTREACHED();
  return 0;
}

double Var::AsDouble() const {
  if (is_double())
    return var_.value.as_double;
  if (is_int())
    return static_cast<double>(var_.value.as_int);
  PP_NOTREACHED();
  return 0.0;
}

std::string Var::AsString() const {
  if (!is_string()) {
    PP_NOTREACHED();
    return std::string();
  }

  if (!ppb_var_f)
    return std::string();
  uint32_t len;
  const char* str = ppb_var_f->VarToUtf8(var_, &len);
  return std::string(str, len);
}

ScriptableObject* Var::AsScriptableObject() const {
  if (!is_object()) {
    PP_NOTREACHED();
  } else if (ppb_var_f) {
    void* object = NULL;
    if (ppb_var_f->IsInstanceOf(var_, ScriptableObject::GetClass(), &object)) {
      return reinterpret_cast<ScriptableObject*>(object);
    }
  }
  return NULL;
}

bool Var::HasProperty(const Var& name, Var* exception) const {
  if (!ppb_var_f)
    return false;
  return ppb_var_f->HasProperty(var_, name.var_, OutException(exception).get());
}

bool Var::HasMethod(const Var& name, Var* exception) const {
  if (!ppb_var_f)
    return false;
  return ppb_var_f->HasMethod(var_, name.var_, OutException(exception).get());
}

Var Var::GetProperty(const Var& name, Var* exception) const {
  if (!ppb_var_f)
    return Var();
  return Var(PassRef(), ppb_var_f->GetProperty(var_, name.var_,
                                               OutException(exception).get()));
}

void Var::GetAllPropertyNames(std::vector<Var>* properties,
                              Var* exception) const {
  if (!ppb_var_f)
    return;
  PP_Var* props = NULL;
  uint32_t prop_count = 0;
  ppb_var_f->GetAllPropertyNames(var_, &prop_count, &props,
                                 OutException(exception).get());
  if (!prop_count)
    return;
  properties->resize(prop_count);
  for (uint32_t i = 0; i < prop_count; ++i) {
    Var temp(PassRef(), props[i]);
    (*properties)[i] = temp;
  }
  Module::Get()->core()->MemFree(props);
}

void Var::SetProperty(const Var& name, const Var& value, Var* exception) {
  if (!ppb_var_f)
    return;
  ppb_var_f->SetProperty(var_, name.var_, value.var_,
                         OutException(exception).get());
}

void Var::RemoveProperty(const Var& name, Var* exception) {
  if (!ppb_var_f)
    return;
  ppb_var_f->RemoveProperty(var_, name.var_, OutException(exception).get());
}

Var Var::Call(const Var& method_name, uint32_t argc, Var* argv,
              Var* exception) {
  if (!ppb_var_f)
    return Var();
  if (argc > 0) {
    std::vector<PP_Var> args;
    args.reserve(argc);
    for (size_t i = 0; i < argc; i++)
      args.push_back(argv[i].var_);
    return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_,
                                          argc, &args[0],
                                          OutException(exception).get()));
  } else {
    // Don't try to get the address of a vector if it's empty.
    return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 0, NULL,
                                          OutException(exception).get()));
  }
}

Var Var::Construct(uint32_t argc, Var* argv, Var* exception) const {
  if (!ppb_var_f)
    return Var();
  if (argc > 0) {
    std::vector<PP_Var> args;
    args.reserve(argc);
    for (size_t i = 0; i < argc; i++)
      args.push_back(argv[i].var_);
    return Var(PassRef(), ppb_var_f->Construct(var_, argc, &args[0],
                                               OutException(exception).get()));
  } else {
    // Don't try to get the address of a vector if it's empty.
    return Var(PassRef(), ppb_var_f->Construct(var_, 0, NULL,
                                               OutException(exception).get()));
  }
}

Var Var::Call(const Var& method_name, Var* exception) {
  if (!ppb_var_f)
    return Var();
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 0, NULL,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[1] = {arg1.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 1, args,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2,
              Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[2] = {arg1.var_, arg2.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 2, args,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2,
              const Var& arg3, Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[3] = {arg1.var_, arg2.var_, arg3.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 3, args,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2,
              const Var& arg3, const Var& arg4, Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[4] = {arg1.var_, arg2.var_, arg3.var_, arg4.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 4, args,
                                        OutException(exception).get()));
}

std::string Var::DebugString() const {
  char buf[256];
  if (is_undefined())
    snprintf(buf, sizeof(buf), "Var<UNDEFINED>");
  else if (is_null())
    snprintf(buf, sizeof(buf), "Var<NULL>");
  else if (is_bool())
    snprintf(buf, sizeof(buf), AsBool() ? "Var<true>" : "Var<false>");
  else if (is_int())
    // Note that the following static_cast is necessary because
    // NativeClient's int32_t is actually "long".
    // TODO(sehr,polina): remove this after newlib is changed.
    snprintf(buf, sizeof(buf), "Var<%d>", static_cast<int>(AsInt()));
  else if (is_double())
    snprintf(buf, sizeof(buf), "Var<%f>", AsDouble());
  else if (is_string())
    snprintf(buf, sizeof(buf), "Var<'%s'>", AsString().c_str());
  else if (is_object())
    snprintf(buf, sizeof(buf), "Var<OBJECT>");
  return buf;
}

}  // namespace pp
<commit_msg>Fix a bug in pp:Var (var.cc) where DebugString could throw an exception on Windows; replace _snprintf_s, which doesn't have the same signature as snprintf, with sprintf_s, which has the same function signature. Check length of string vars and truncate values (adding ellipsis at end) if the won't fit in our fixed size buffer. TEST=manual BUG=none (found during testing in Chrome) Review URL: http://codereview.chromium.org/5559009<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/cpp/var.h"

#include <stdio.h>
#include <string.h>

#include <algorithm>

#include "ppapi/c/pp_var.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/cpp/common.h"
#include "ppapi/cpp/logging.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"

// Define equivalent to snprintf on Windows.
#if defined(_MSC_VER)
#  define snprintf sprintf_s
#endif

namespace {

DeviceFuncs<PPB_Var_Deprecated> ppb_var_f(PPB_VAR_DEPRECATED_INTERFACE);

// Technically you can call AddRef and Release on any Var, but it may involve
// cross-process calls depending on the plugin. This is an optimization so we
// only do refcounting on the necessary objects.
inline bool NeedsRefcounting(const PP_Var& var) {
  return var.type == PP_VARTYPE_STRING || var.type == PP_VARTYPE_OBJECT;
}

}  // namespace

namespace pp {

using namespace deprecated;

Var::Var() {
  var_.type = PP_VARTYPE_UNDEFINED;
  needs_release_ = false;
}

Var::Var(Null) {
  var_.type = PP_VARTYPE_NULL;
  needs_release_ = false;
}

Var::Var(bool b) {
  var_.type = PP_VARTYPE_BOOL;
  var_.value.as_bool = BoolToPPBool(b);
  needs_release_ = false;
}

Var::Var(int32_t i) {
  var_.type = PP_VARTYPE_INT32;
  var_.value.as_int = i;
  needs_release_ = false;
}

Var::Var(double d) {
  var_.type = PP_VARTYPE_DOUBLE;
  var_.value.as_double = d;
  needs_release_ = false;
}

Var::Var(const char* utf8_str) {
  if (ppb_var_f) {
    uint32_t len = utf8_str ? static_cast<uint32_t>(strlen(utf8_str)) : 0;
    var_ = ppb_var_f->VarFromUtf8(Module::Get()->pp_module(), utf8_str, len);
  } else {
    var_.type = PP_VARTYPE_NULL;
  }
  needs_release_ = (var_.type == PP_VARTYPE_STRING);
}

Var::Var(const std::string& utf8_str) {
  if (ppb_var_f) {
    var_ = ppb_var_f->VarFromUtf8(Module::Get()->pp_module(),
                                  utf8_str.c_str(),
                                  static_cast<uint32_t>(utf8_str.size()));
  } else {
    var_.type = PP_VARTYPE_NULL;
  }
  needs_release_ = (var_.type == PP_VARTYPE_STRING);
}

Var::Var(ScriptableObject* object) {
  if (ppb_var_f) {
    var_ = ppb_var_f->CreateObject(Module::Get()->pp_module(),
                                   object->GetClass(), object);
    needs_release_ = true;
  } else {
    var_.type = PP_VARTYPE_NULL;
    needs_release_ = false;
  }
}

Var::Var(const Var& other) {
  var_ = other.var_;
  if (NeedsRefcounting(var_)) {
    if (ppb_var_f) {
      needs_release_ = true;
      ppb_var_f->AddRef(var_);
    } else {
      var_.type = PP_VARTYPE_NULL;
      needs_release_ = false;
    }
  } else {
    needs_release_ = false;
  }
}

Var::~Var() {
  if (needs_release_ && ppb_var_f)
    ppb_var_f->Release(var_);
}

Var& Var::operator=(const Var& other) {
  if (needs_release_ && ppb_var_f)
    ppb_var_f->Release(var_);
  var_ = other.var_;
  if (NeedsRefcounting(var_)) {
    if (ppb_var_f) {
      needs_release_ = true;
      ppb_var_f->AddRef(var_);
    } else {
      var_.type = PP_VARTYPE_NULL;
      needs_release_ = false;
    }
  } else {
    needs_release_ = false;
  }
  return *this;
}

bool Var::operator==(const Var& other) const {
  if (var_.type != other.var_.type)
    return false;
  switch (var_.type) {
    case PP_VARTYPE_UNDEFINED:
    case PP_VARTYPE_NULL:
      return true;
    case PP_VARTYPE_BOOL:
      return AsBool() == other.AsBool();
    case PP_VARTYPE_INT32:
      return AsInt() == other.AsInt();
    case PP_VARTYPE_DOUBLE:
      return AsDouble() == other.AsDouble();
    case PP_VARTYPE_STRING:
      if (var_.value.as_id == other.var_.value.as_id)
        return true;
      return AsString() == other.AsString();
    // TODO(neb): Document that this is === and not ==, unlike strings.
    case PP_VARTYPE_OBJECT:
      return var_.value.as_id == other.var_.value.as_id;
    default:
      return false;
  }
}

bool Var::AsBool() const {
  if (!is_bool()) {
    PP_NOTREACHED();
    return false;
  }
  return PPBoolToBool(var_.value.as_bool);
}

int32_t Var::AsInt() const {
  if (is_int())
    return var_.value.as_int;
  if (is_double())
    return static_cast<int>(var_.value.as_double);
  PP_NOTREACHED();
  return 0;
}

double Var::AsDouble() const {
  if (is_double())
    return var_.value.as_double;
  if (is_int())
    return static_cast<double>(var_.value.as_int);
  PP_NOTREACHED();
  return 0.0;
}

std::string Var::AsString() const {
  if (!is_string()) {
    PP_NOTREACHED();
    return std::string();
  }

  if (!ppb_var_f)
    return std::string();
  uint32_t len;
  const char* str = ppb_var_f->VarToUtf8(var_, &len);
  return std::string(str, len);
}

ScriptableObject* Var::AsScriptableObject() const {
  if (!is_object()) {
    PP_NOTREACHED();
  } else if (ppb_var_f) {
    void* object = NULL;
    if (ppb_var_f->IsInstanceOf(var_, ScriptableObject::GetClass(), &object)) {
      return reinterpret_cast<ScriptableObject*>(object);
    }
  }
  return NULL;
}

bool Var::HasProperty(const Var& name, Var* exception) const {
  if (!ppb_var_f)
    return false;
  return ppb_var_f->HasProperty(var_, name.var_, OutException(exception).get());
}

bool Var::HasMethod(const Var& name, Var* exception) const {
  if (!ppb_var_f)
    return false;
  return ppb_var_f->HasMethod(var_, name.var_, OutException(exception).get());
}

Var Var::GetProperty(const Var& name, Var* exception) const {
  if (!ppb_var_f)
    return Var();
  return Var(PassRef(), ppb_var_f->GetProperty(var_, name.var_,
                                               OutException(exception).get()));
}

void Var::GetAllPropertyNames(std::vector<Var>* properties,
                              Var* exception) const {
  if (!ppb_var_f)
    return;
  PP_Var* props = NULL;
  uint32_t prop_count = 0;
  ppb_var_f->GetAllPropertyNames(var_, &prop_count, &props,
                                 OutException(exception).get());
  if (!prop_count)
    return;
  properties->resize(prop_count);
  for (uint32_t i = 0; i < prop_count; ++i) {
    Var temp(PassRef(), props[i]);
    (*properties)[i] = temp;
  }
  Module::Get()->core()->MemFree(props);
}

void Var::SetProperty(const Var& name, const Var& value, Var* exception) {
  if (!ppb_var_f)
    return;
  ppb_var_f->SetProperty(var_, name.var_, value.var_,
                         OutException(exception).get());
}

void Var::RemoveProperty(const Var& name, Var* exception) {
  if (!ppb_var_f)
    return;
  ppb_var_f->RemoveProperty(var_, name.var_, OutException(exception).get());
}

Var Var::Call(const Var& method_name, uint32_t argc, Var* argv,
              Var* exception) {
  if (!ppb_var_f)
    return Var();
  if (argc > 0) {
    std::vector<PP_Var> args;
    args.reserve(argc);
    for (size_t i = 0; i < argc; i++)
      args.push_back(argv[i].var_);
    return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_,
                                          argc, &args[0],
                                          OutException(exception).get()));
  } else {
    // Don't try to get the address of a vector if it's empty.
    return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 0, NULL,
                                          OutException(exception).get()));
  }
}

Var Var::Construct(uint32_t argc, Var* argv, Var* exception) const {
  if (!ppb_var_f)
    return Var();
  if (argc > 0) {
    std::vector<PP_Var> args;
    args.reserve(argc);
    for (size_t i = 0; i < argc; i++)
      args.push_back(argv[i].var_);
    return Var(PassRef(), ppb_var_f->Construct(var_, argc, &args[0],
                                               OutException(exception).get()));
  } else {
    // Don't try to get the address of a vector if it's empty.
    return Var(PassRef(), ppb_var_f->Construct(var_, 0, NULL,
                                               OutException(exception).get()));
  }
}

Var Var::Call(const Var& method_name, Var* exception) {
  if (!ppb_var_f)
    return Var();
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 0, NULL,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[1] = {arg1.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 1, args,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2,
              Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[2] = {arg1.var_, arg2.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 2, args,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2,
              const Var& arg3, Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[3] = {arg1.var_, arg2.var_, arg3.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 3, args,
                                        OutException(exception).get()));
}

Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2,
              const Var& arg3, const Var& arg4, Var* exception) {
  if (!ppb_var_f)
    return Var();
  PP_Var args[4] = {arg1.var_, arg2.var_, arg3.var_, arg4.var_};
  return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 4, args,
                                        OutException(exception).get()));
}

std::string Var::DebugString() const {
  char buf[256];
  if (is_undefined()) {
    snprintf(buf, sizeof(buf), "Var<UNDEFINED>");
  } else if (is_null()) {
    snprintf(buf, sizeof(buf), "Var<NULL>");
  } else if (is_bool()) {
    snprintf(buf, sizeof(buf), AsBool() ? "Var<true>" : "Var<false>");
  } else if (is_int()) {
    // Note that the following static_cast is necessary because
    // NativeClient's int32_t is actually "long".
    // TODO(sehr,polina): remove this after newlib is changed.
    snprintf(buf, sizeof(buf), "Var<%d>", static_cast<int>(AsInt()));
  } else if (is_double()) {
    snprintf(buf, sizeof(buf), "Var<%f>", AsDouble());
  } else if (is_string()) {
    char format[] = "Var<'%s'>";
    size_t decoration = sizeof(format) - 2;  // The %s is removed.
    size_t available = sizeof(buf) - decoration;
    std::string str = AsString();
    if (str.length() > available) {
      str.resize(available - 3);  // Reserve space for ellipsis.
      str.append("...");
    }
    snprintf(buf, sizeof(buf), format, str.c_str());
  } else if (is_object()) {
    snprintf(buf, sizeof(buf), "Var<OBJECT>");
  }
  return buf;
}

}  // namespace pp
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SoftwareTimer class implementation
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-11-15
 */

#include "distortos/SoftwareTimer.hpp"

namespace distortos
{

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

SoftwareTimer::SoftwareTimer() :
		softwareTimerControlBlock_{softwareTimerRunner, *this}
{

}

SoftwareTimer::~SoftwareTimer()
{

}

bool SoftwareTimer::isRunning() const
{
	return softwareTimerControlBlock_.isRunning();
}

void SoftwareTimer::start(const TickClock::duration duration)
{
	softwareTimerControlBlock_.start(duration);
}

void SoftwareTimer::start(const TickClock::time_point timePoint)
{
	softwareTimerControlBlock_.start(timePoint);
}

void SoftwareTimer::stop()
{
	softwareTimerControlBlock_.stop();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private static functions
+---------------------------------------------------------------------------------------------------------------------*/

void SoftwareTimer::softwareTimerRunner(SoftwareTimer& softwareTimer)
{
	softwareTimer.run();
}

}	// namespace distortos
<commit_msg>SoftwareTimer::start(TickClock::duration): use other overload<commit_after>/**
 * \file
 * \brief SoftwareTimer class implementation
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-11-15
 */

#include "distortos/SoftwareTimer.hpp"

namespace distortos
{

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

SoftwareTimer::SoftwareTimer() :
		softwareTimerControlBlock_{softwareTimerRunner, *this}
{

}

SoftwareTimer::~SoftwareTimer()
{

}

bool SoftwareTimer::isRunning() const
{
	return softwareTimerControlBlock_.isRunning();
}

void SoftwareTimer::start(const TickClock::duration duration)
{
	const auto now = TickClock::now();
	start(now + duration + decltype(duration){1});
}

void SoftwareTimer::start(const TickClock::time_point timePoint)
{
	softwareTimerControlBlock_.start(timePoint);
}

void SoftwareTimer::stop()
{
	softwareTimerControlBlock_.stop();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private static functions
+---------------------------------------------------------------------------------------------------------------------*/

void SoftwareTimer::softwareTimerRunner(SoftwareTimer& softwareTimer)
{
	softwareTimer.run();
}

}	// namespace distortos
<|endoftext|>


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

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

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

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

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

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

#include "thermometer.h"
#include "ptreferential/ptreferential.h"
#include "time.h"
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/range/algorithm/sort.hpp>
#include "type/type.h"

namespace navitia {
namespace timetables {

static uint32_t get_lower_bound(std::vector<vector_size>& pre_computed_lb, type::idx_t max_sp) {
    uint32_t result = 0;
    for (unsigned int sp = 0; sp < (max_sp + 1); ++sp) {
        result += std::max(pre_computed_lb[0][sp], pre_computed_lb[1][sp]);
    }
    return result;
}

static std::vector<vector_size> pre_compute_lower_bound(const std::vector<vector_idx>& journey_patterns,
                                                        type::idx_t max_sp) {
    std::vector<vector_size> lower_bounds;
    for (auto journey_pattern : journey_patterns) {
        lower_bounds.push_back(vector_size());
        lower_bounds.back().insert(lower_bounds.back().begin(), max_sp + 1, 0);
        for (auto sp : journey_pattern) {
            ++lower_bounds.back()[sp];
        }
    }
    return lower_bounds;
}

std::pair<vector_idx, bool> Thermometer::recc(std::vector<vector_idx>& journey_patterns,
                                              std::vector<vector_size>& pre_computed_lb,
                                              const uint32_t lower_bound_,
                                              type::idx_t max_sp,
                                              const uint32_t upper_bound_,
                                              int depth) {
    ++depth;
    ++nb_branches;
    uint32_t lower_bound = lower_bound_, upper_bound = upper_bound_;
    vector_idx result;

    vector_idx possibilities = generate_possibilities(journey_patterns, pre_computed_lb);
    bool res_bool = possibilities.empty();
    for (auto poss_spidx : possibilities) {
        if (nb_branches > 5000 && !result.empty())
            break;
        int temp1 = std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
        std::vector<uint32_t> to_retail = untail(journey_patterns, poss_spidx, pre_computed_lb);
        lower_bound = lower_bound - temp1 + std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);

        uint32_t u = upper_bound;
        if (u != std::numeric_limits<uint32_t>::max()) {
            --u;
        }

        if (lower_bound >= u) {
            int temp = std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
            retail(journey_patterns, poss_spidx, to_retail, pre_computed_lb);
            lower_bound = lower_bound - temp + std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
        } else {
            std::pair<vector_idx, bool> tmp = recc(journey_patterns, pre_computed_lb, lower_bound, max_sp, u, depth);
            int temp = std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
            retail(journey_patterns, poss_spidx, to_retail, pre_computed_lb);
            lower_bound = lower_bound - temp + std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
            if (tmp.second) {
                tmp.first.push_back(poss_spidx);
                if (!res_bool || (tmp.second && tmp.first.size() < upper_bound)) {
                    result = tmp.first;
                    res_bool = true;
                    upper_bound = result.size();
                }

                if (upper_bound == lower_bound) {
                    break;
                }
            }
        }
    }

    return std::make_pair(result, res_bool);
}

static uint32_t get_max_sp(const std::vector<vector_idx>& journey_patterns) {
    uint32_t max_sp = std::numeric_limits<uint32_t>::min();

    for (auto journey_pattern : journey_patterns) {
        for (auto i : journey_pattern) {
            if (i > max_sp)
                max_sp = i;
        }
    }

    return max_sp;
}

void Thermometer::generate_thermometer(const type::Route* route) {
    std::set<vector_idx> stop_point_lists;
    route->for_each_vehicle_journey([&](const type::VehicleJourney& vj) {
        vector_idx stop_point_list;
        for (const auto& st : vj.stop_time_list) {
            stop_point_list.push_back(st.stop_point->idx);
        }
        stop_point_lists.insert(std::move(stop_point_list));
        return true;
    });
    generate_thermometer(std::vector<vector_idx>(stop_point_lists.begin(), stop_point_lists.end()));
}

// Define types for next function 'generate_topological_thermometer'
struct VertexProperties {
    type::idx_t idx;
    VertexProperties() : idx(0) {}
    VertexProperties(type::idx_t const& i) : idx(i) {}
};
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperties>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

// Generate an topologicaly exact thermometer
// return false if topological sort fail (because of a cycle)
// return true if succeed
bool Thermometer::generate_topological_thermometer(const std::vector<vector_idx>& stop_point_lists) {
    Graph stop_point_graph;
    std::map<type::idx_t, Vertex> vertex_map;
    for (const auto& v : stop_point_lists) {
        if (v.empty()) {
            continue;
        }
        bool first = true;
        Vertex previous_vx = v.front();
        for (auto sp : v) {
            Vertex current_vx;

            // We don't add a vertex twice
            auto it = vertex_map.find(sp);
            if (it == vertex_map.end()) {
                current_vx = boost::add_vertex(VertexProperties(sp), stop_point_graph);
                vertex_map[sp] = current_vx;
            } else {
                current_vx = it->second;
            }
            if (!first) {
                boost::add_edge(previous_vx, current_vx, stop_point_graph);
            }
            first = false;
            previous_vx = current_vx;
        }
    }

    std::vector<Vertex> c;
    try {
        boost::topological_sort(stop_point_graph, std::back_inserter(c));
    } catch (const boost::not_a_dag&) {
        // Graph contains cycles : we need to try custom algorithm
        return false;
    }

    // Build thermometer with sort result
    for (auto it = c.rbegin(); it != c.rend(); ++it) {
        thermometer.push_back(stop_point_graph[*it].idx);
    }
    return true;
}

void Thermometer::generate_thermometer(const std::vector<vector_idx>& sps) {
    // We prefere to have the biggest jp first, because the heuristic
    // has less chance to do bad choice if critical jp are used first.
    std::vector<vector_idx> stop_point_lists = sps;
    boost::range::sort(stop_point_lists, [](const vector_idx& a, const vector_idx& b) { return a.size() > b.size(); });

    if (stop_point_lists.size() > 1) {
        // Try a topological_sort first
        // If succeed, return, else use custom algorithm
        if (generate_topological_thermometer(stop_point_lists)) {
            return;
        }

        uint32_t max_sp = get_max_sp(stop_point_lists);
        nb_branches = 0;
        std::vector<vector_idx> req;
        for (auto v : stop_point_lists) {
            if (req.empty()) {
                req.push_back(v);
                continue;
            }
            nb_branches = 0;
            req.push_back(v);
            auto plb = pre_compute_lower_bound(req, max_sp);
            uint32_t lowerbound = get_lower_bound(plb, max_sp);
            auto tp = recc(req, plb, lowerbound, max_sp).first;
            req.clear();

            req.push_back(tp);
        }
        thermometer = req.back();
    } else if (stop_point_lists.size() == 1) {
        thermometer = stop_point_lists.back();
    }
}

vector_idx Thermometer::get_thermometer() const {
    return thermometer;
}

std::vector<uint32_t> Thermometer::stop_times_order(const type::VehicleJourney& vj) const {
    vector_idx tmp;
    for (const auto& st : vj.stop_time_list) {
        tmp.push_back(st.stop_point->idx);
    }

    return stop_times_order_helper(tmp);
}

std::vector<uint32_t> Thermometer::stop_times_order_helper(const vector_idx& stop_point_list) const {
    std::vector<uint32_t> result;
    auto it = thermometer.begin();
    for (type::idx_t spidx : stop_point_list) {
        it = std::find(it, thermometer.end(), spidx);
        if (it == thermometer.end()) {
            throw cant_match(spidx);
        } else {
            result.push_back(distance(thermometer.begin(), it));
        }
        ++it;
    }
    return result;
}

vector_idx Thermometer::generate_possibilities(const std::vector<vector_idx>& journey_patterns,
                                               std::vector<vector_size>& pre_computed_lb) {
    // There is no possible solution
    if (journey_patterns[0].empty() && journey_patterns[1].empty()) {
        return {};
    }

    // If journey_pattern 1 is empty, or if the journey_pattern last element is not present in journey_pattern0, we
    // return the head of journey_pattern 1
    if (journey_patterns[0].empty()
        || (!journey_patterns[1].empty() && pre_computed_lb[0][journey_patterns[1].back()] == 0)) {
        return {journey_patterns[1].back()};
    } else if (journey_patterns[1].empty()
               || (!journey_patterns[0].empty()
                   && pre_computed_lb[1][journey_patterns[0].back()] == 0)) {  // The same for journey_pattern 0
        return {journey_patterns[0].back()};
    }

    auto count1 = std::count(journey_patterns[0].begin(), journey_patterns[0].end(), journey_patterns[1].back());
    auto count2 = std::count(journey_patterns[1].begin(), journey_patterns[1].end(), journey_patterns[0].back());

    if (count1 > count2) {
        return {journey_patterns[0].back(), journey_patterns[1].back()};
    } else if (count1 < count2) {
        return {journey_patterns[1].back(), journey_patterns[0].back()};
    } else if (journey_patterns[0].size() < journey_patterns[1].size()) {
        return {journey_patterns[0].back(), journey_patterns[1].back()};
    } else {
        return {journey_patterns[1].back(), journey_patterns[0].back()};
    }
}

std::vector<uint32_t> Thermometer::untail(std::vector<vector_idx>& journey_patterns,
                                          type::idx_t spidx,
                                          std::vector<vector_size>& pre_computed_lb) {
    std::vector<uint32_t> result;
    if (spidx != type::invalid_idx) {
        if ((journey_patterns[0].size() > 0) && (journey_patterns[0].back() == spidx)) {
            journey_patterns[0].pop_back();
            result.push_back(0);
            --pre_computed_lb[0][spidx];
        }
        if ((journey_patterns[1].size() > 0) && (journey_patterns[1].back() == spidx)) {
            journey_patterns[1].pop_back();
            result.push_back(1);
            --pre_computed_lb[1][spidx];
        }
    }
    return result;
}

void Thermometer::retail(std::vector<vector_idx>& journey_patterns,
                         type::idx_t spidx,
                         const std::vector<uint32_t>& to_retail,
                         std::vector<vector_size>& pre_computed_lb) {
    for (auto i : to_retail) {
        journey_patterns[i].push_back(spidx);
        ++pre_computed_lb[i][spidx];
    }
}

}  // namespace timetables
}  // namespace navitia
<commit_msg>clean old thermometer result before new run<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

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

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

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

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

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

#include "thermometer.h"
#include "ptreferential/ptreferential.h"
#include "time.h"
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/range/algorithm/sort.hpp>
#include "type/type.h"

namespace navitia {
namespace timetables {

static uint32_t get_lower_bound(std::vector<vector_size>& pre_computed_lb, type::idx_t max_sp) {
    uint32_t result = 0;
    for (unsigned int sp = 0; sp < (max_sp + 1); ++sp) {
        result += std::max(pre_computed_lb[0][sp], pre_computed_lb[1][sp]);
    }
    return result;
}

static std::vector<vector_size> pre_compute_lower_bound(const std::vector<vector_idx>& journey_patterns,
                                                        type::idx_t max_sp) {
    std::vector<vector_size> lower_bounds;
    for (auto journey_pattern : journey_patterns) {
        lower_bounds.push_back(vector_size());
        lower_bounds.back().insert(lower_bounds.back().begin(), max_sp + 1, 0);
        for (auto sp : journey_pattern) {
            ++lower_bounds.back()[sp];
        }
    }
    return lower_bounds;
}

std::pair<vector_idx, bool> Thermometer::recc(std::vector<vector_idx>& journey_patterns,
                                              std::vector<vector_size>& pre_computed_lb,
                                              const uint32_t lower_bound_,
                                              type::idx_t max_sp,
                                              const uint32_t upper_bound_,
                                              int depth) {
    ++depth;
    ++nb_branches;
    uint32_t lower_bound = lower_bound_, upper_bound = upper_bound_;
    vector_idx result;

    vector_idx possibilities = generate_possibilities(journey_patterns, pre_computed_lb);
    bool res_bool = possibilities.empty();
    for (auto poss_spidx : possibilities) {
        if (nb_branches > 5000 && !result.empty())
            break;
        int temp1 = std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
        std::vector<uint32_t> to_retail = untail(journey_patterns, poss_spidx, pre_computed_lb);
        lower_bound = lower_bound - temp1 + std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);

        uint32_t u = upper_bound;
        if (u != std::numeric_limits<uint32_t>::max()) {
            --u;
        }

        if (lower_bound >= u) {
            int temp = std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
            retail(journey_patterns, poss_spidx, to_retail, pre_computed_lb);
            lower_bound = lower_bound - temp + std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
        } else {
            std::pair<vector_idx, bool> tmp = recc(journey_patterns, pre_computed_lb, lower_bound, max_sp, u, depth);
            int temp = std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
            retail(journey_patterns, poss_spidx, to_retail, pre_computed_lb);
            lower_bound = lower_bound - temp + std::max(pre_computed_lb[0][poss_spidx], pre_computed_lb[1][poss_spidx]);
            if (tmp.second) {
                tmp.first.push_back(poss_spidx);
                if (!res_bool || (tmp.second && tmp.first.size() < upper_bound)) {
                    result = tmp.first;
                    res_bool = true;
                    upper_bound = result.size();
                }

                if (upper_bound == lower_bound) {
                    break;
                }
            }
        }
    }

    return std::make_pair(result, res_bool);
}

static uint32_t get_max_sp(const std::vector<vector_idx>& journey_patterns) {
    uint32_t max_sp = std::numeric_limits<uint32_t>::min();

    for (auto journey_pattern : journey_patterns) {
        for (auto i : journey_pattern) {
            if (i > max_sp)
                max_sp = i;
        }
    }

    return max_sp;
}

void Thermometer::generate_thermometer(const type::Route* route) {
    std::set<vector_idx> stop_point_lists;
    route->for_each_vehicle_journey([&](const type::VehicleJourney& vj) {
        vector_idx stop_point_list;
        for (const auto& st : vj.stop_time_list) {
            stop_point_list.push_back(st.stop_point->idx);
        }
        stop_point_lists.insert(std::move(stop_point_list));
        return true;
    });
    generate_thermometer(std::vector<vector_idx>(stop_point_lists.begin(), stop_point_lists.end()));
}

// Define types for next function 'generate_topological_thermometer'
struct VertexProperties {
    type::idx_t idx;
    VertexProperties() : idx(0) {}
    VertexProperties(type::idx_t const& i) : idx(i) {}
};
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperties>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

// Generate an topologicaly exact thermometer
// return false if topological sort fail (because of a cycle)
// return true if succeed
bool Thermometer::generate_topological_thermometer(const std::vector<vector_idx>& stop_point_lists) {
    Graph stop_point_graph;
    std::map<type::idx_t, Vertex> vertex_map;
    for (const auto& v : stop_point_lists) {
        if (v.empty()) {
            continue;
        }
        bool first = true;
        Vertex previous_vx = v.front();
        for (auto sp : v) {
            Vertex current_vx;

            // We don't add a vertex twice
            auto it = vertex_map.find(sp);
            if (it == vertex_map.end()) {
                current_vx = boost::add_vertex(VertexProperties(sp), stop_point_graph);
                vertex_map[sp] = current_vx;
            } else {
                current_vx = it->second;
            }
            if (!first) {
                boost::add_edge(previous_vx, current_vx, stop_point_graph);
            }
            first = false;
            previous_vx = current_vx;
        }
    }

    std::vector<Vertex> c;
    try {
        boost::topological_sort(stop_point_graph, std::back_inserter(c));
    } catch (const boost::not_a_dag&) {
        // Graph contains cycles : we need to try custom algorithm
        return false;
    }

    // Build thermometer with sort result
    for (auto it = c.rbegin(); it != c.rend(); ++it) {
        thermometer.push_back(stop_point_graph[*it].idx);
    }
    return true;
}

void Thermometer::generate_thermometer(const std::vector<vector_idx>& sps) {
    // We prefere to have the biggest jp first, because the heuristic
    // has less chance to do bad choice if critical jp are used first.
    std::vector<vector_idx> stop_point_lists = sps;
    boost::range::sort(stop_point_lists, [](const vector_idx& a, const vector_idx& b) { return a.size() > b.size(); });

    if (stop_point_lists.size() > 1) {
        // Clean old results
        thermometer.clear();
        // Try a topological_sort first
        // If succeed, return, else use custom algorithm
        if (generate_topological_thermometer(stop_point_lists)) {
            return;
        }

        uint32_t max_sp = get_max_sp(stop_point_lists);
        nb_branches = 0;
        std::vector<vector_idx> req;
        for (auto v : stop_point_lists) {
            if (req.empty()) {
                req.push_back(v);
                continue;
            }
            nb_branches = 0;
            req.push_back(v);
            auto plb = pre_compute_lower_bound(req, max_sp);
            uint32_t lowerbound = get_lower_bound(plb, max_sp);
            auto tp = recc(req, plb, lowerbound, max_sp).first;
            req.clear();

            req.push_back(tp);
        }
        thermometer = req.back();
    } else if (stop_point_lists.size() == 1) {
        thermometer = stop_point_lists.back();
    }
}

vector_idx Thermometer::get_thermometer() const {
    return thermometer;
}

std::vector<uint32_t> Thermometer::stop_times_order(const type::VehicleJourney& vj) const {
    vector_idx tmp;
    for (const auto& st : vj.stop_time_list) {
        tmp.push_back(st.stop_point->idx);
    }

    return stop_times_order_helper(tmp);
}

std::vector<uint32_t> Thermometer::stop_times_order_helper(const vector_idx& stop_point_list) const {
    std::vector<uint32_t> result;
    auto it = thermometer.begin();
    for (type::idx_t spidx : stop_point_list) {
        it = std::find(it, thermometer.end(), spidx);
        if (it == thermometer.end()) {
            throw cant_match(spidx);
        } else {
            result.push_back(distance(thermometer.begin(), it));
        }
        ++it;
    }
    return result;
}

vector_idx Thermometer::generate_possibilities(const std::vector<vector_idx>& journey_patterns,
                                               std::vector<vector_size>& pre_computed_lb) {
    // There is no possible solution
    if (journey_patterns[0].empty() && journey_patterns[1].empty()) {
        return {};
    }

    // If journey_pattern 1 is empty, or if the journey_pattern last element is not present in journey_pattern0, we
    // return the head of journey_pattern 1
    if (journey_patterns[0].empty()
        || (!journey_patterns[1].empty() && pre_computed_lb[0][journey_patterns[1].back()] == 0)) {
        return {journey_patterns[1].back()};
    } else if (journey_patterns[1].empty()
               || (!journey_patterns[0].empty()
                   && pre_computed_lb[1][journey_patterns[0].back()] == 0)) {  // The same for journey_pattern 0
        return {journey_patterns[0].back()};
    }

    auto count1 = std::count(journey_patterns[0].begin(), journey_patterns[0].end(), journey_patterns[1].back());
    auto count2 = std::count(journey_patterns[1].begin(), journey_patterns[1].end(), journey_patterns[0].back());

    if (count1 > count2) {
        return {journey_patterns[0].back(), journey_patterns[1].back()};
    } else if (count1 < count2) {
        return {journey_patterns[1].back(), journey_patterns[0].back()};
    } else if (journey_patterns[0].size() < journey_patterns[1].size()) {
        return {journey_patterns[0].back(), journey_patterns[1].back()};
    } else {
        return {journey_patterns[1].back(), journey_patterns[0].back()};
    }
}

std::vector<uint32_t> Thermometer::untail(std::vector<vector_idx>& journey_patterns,
                                          type::idx_t spidx,
                                          std::vector<vector_size>& pre_computed_lb) {
    std::vector<uint32_t> result;
    if (spidx != type::invalid_idx) {
        if ((journey_patterns[0].size() > 0) && (journey_patterns[0].back() == spidx)) {
            journey_patterns[0].pop_back();
            result.push_back(0);
            --pre_computed_lb[0][spidx];
        }
        if ((journey_patterns[1].size() > 0) && (journey_patterns[1].back() == spidx)) {
            journey_patterns[1].pop_back();
            result.push_back(1);
            --pre_computed_lb[1][spidx];
        }
    }
    return result;
}

void Thermometer::retail(std::vector<vector_idx>& journey_patterns,
                         type::idx_t spidx,
                         const std::vector<uint32_t>& to_retail,
                         std::vector<vector_size>& pre_computed_lb) {
    for (auto i : to_retail) {
        journey_patterns[i].push_back(spidx);
        ++pre_computed_lb[i][spidx];
    }
}

}  // namespace timetables
}  // namespace navitia
<|endoftext|>


<commit_before>/*
 * gl/ATWinBar.cpp
 *
 * Copyright (C) 2016 MegaMol Team
 * Alle Rechte vorbehalten.
 */
#include "stdafx.h"
#ifdef HAS_ANTTWEAKBAR
#include "gl/Window.h"
#include "gl/ATWinBar.h"
#include <sstream>
#include "GLFW/glfw3.h"
#include "gl/ATBUILayer.h"
#include "utility/ParamFileManager.h"

using namespace megamol;
using namespace megamol::console;

gl::ATWinBar::ATWinBar(ATBUILayer& layer, const char* wndName) : ATBar("winBar"), layer(layer),
        winX(0), winY(0), winW(0), winH(0), winSizePresets() {

    winSizePresets[0] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 256, 256);
    winSizePresets[1] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 512, 512);
    winSizePresets[2] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 1024, 1024);
    winSizePresets[3] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 1280, 720);
    winSizePresets[4] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 1920, 1080);

    std::stringstream def;
    def << Name() << " "
        << "label='MegaMol - " << wndName << "' "
        << "help='Options regarding the Window and MegaMol Instance' "
        << "color='225 230 235' alpha='192' text='dark' "
        << "position='48 48' "
        << "size='256 256' valueswidth='128' ";
    ::TwDefine(def.str().c_str());

    // FPS
    ::TwAddVarRO(Handle(), "fps", TW_TYPE_FLOAT, &wnd.FPS(), "label='FPS' help='Rendering performance in frames per second, measured by the time between OpenGL buffer swaps. This value is the mean over several rendering calls or over the rendering calls within some time'");
    ::TwAddVarCB(Handle(), "fpsTitle", TW_TYPE_BOOLCPP,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setShowFPSinWindowTitle),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getShowFPSinWindowTitle),
        &wnd, "label='Show FPS in Window Caption'");
    ::TwAddVarCB(Handle(), "sampTitle", TW_TYPE_BOOLCPP,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setShowSamplesinWindowTitle),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getShowSamplesinWindowTitle),
        &wnd, "label='Show Samples passed in Window Caption'");
    ::TwAddVarCB(Handle(), "primsTitle", TW_TYPE_BOOLCPP,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setShowPrimsinWindowTitle),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getShowPrimsinWindowTitle),
        &wnd, "label='Show Primitives generated in Window Caption'");
    ::TwAddButton(Handle(), "fpsCopy", reinterpret_cast<TwButtonCallback>(&ATWinBar::copyFPS), &wnd, "label='Copy to Clipboard'");
    ::TwAddButton(Handle(), "fpsCopyList", reinterpret_cast<TwButtonCallback>(&ATWinBar::copyFPSList), &wnd, "label='Copy FPS List to Clipboard'");

    // Window placement, size, decorations, etc.
    //  Note: switching to/from fullscreen mode is no longer supported, as GLFW cannot remove/add window decorations after window was created.
    ::TwAddVarRW(Handle(), "winX", TW_TYPE_INT32, &winX, "label='Left' group='Window'");
    ::TwAddVarRW(Handle(), "winY", TW_TYPE_INT32, &winY, "label='Top' group='Window'");
    ::TwAddVarRW(Handle(), "winW", TW_TYPE_UINT32, &winW, "label='Width' group='Window'");
    ::TwAddVarRW(Handle(), "winH", TW_TYPE_UINT32, &winH, "label='Height' group='Window'");
    ::TwAddSeparator(Handle(), nullptr, "group='Window'");
    getWndValues(this);

    ::TwAddButton(Handle(), "winValGet", reinterpret_cast<TwButtonCallback>(&ATWinBar::getWndValues), this, "label='Get Values' group='Window'");
    ::TwAddButton(Handle(), "winValSet", reinterpret_cast<TwButtonCallback>(&ATWinBar::setWndValues), this, "label='Set Values' group='Window'");

    unsigned int i = 0;
    for (auto& wsp : winSizePresets) {
        def.str("");
        def << "winSizePreset" << i;
        std::string name = def.str();
        def.str("");
        def << "label='Set Size " << std::get<1>(wsp) << "x" << std::get<2>(wsp) << "' group='WinSizePre'";
        ::TwAddButton(Handle(), name.c_str(), reinterpret_cast<TwButtonCallback>(&ATWinBar::setWinSizePreset), &wsp, def.str().c_str());
        ++i;
    }
    def.str("");
    def << Name() << "/WinSizePre "
        << "label='Size Presets' "
        << "group='Window' "
        << "opened=true ";
    ::TwDefine(def.str().c_str());
    def.str("");
    def << Name() << "/Window "
        << "opened=false ";
    ::TwDefine(def.str().c_str());

    // GUI show/hide control
    ::TwAddButton(Handle(), "hideGUI", reinterpret_cast<TwButtonCallback>(&ATWinBar::toggleGUI), this, "label='Hide/Show GUI' key=F12");

    // ParamFile
    ::TwAddVarCB(Handle(), "paramFilePath", TW_TYPE_CDSTRING,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setParamFilePath),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getParamFilePath),
        nullptr, "label='ParamFile' group='paramFile'");
    ::TwAddButton(Handle(), "loadParamFile", reinterpret_cast<TwButtonCallback>(&ATWinBar::loadParamFile), nullptr, "label='Load ParamFile' group='paramFile'");
    ::TwAddButton(Handle(), "saveParamFile", reinterpret_cast<TwButtonCallback>(&ATWinBar::saveParamFile), nullptr, "label='Save ParamFile' group='paramFile'");
    def.str("");
    def << Name() << "/paramFile "
        << "label='ParamFile' "
        << "opened=true ";
    ::TwDefine(def.str().c_str());

    // (later: ProjectFile)

    def.str("");
    def << Name() << " "
        << "iconified=true ";
    ::TwDefine(def.str().c_str());

}

gl::ATWinBar::~ATWinBar() {
}

void gl::ATWinBar::getWndValues(ATWinBar *inst) {
    ::glfwGetWindowPos(inst->wnd.WindowHandle(), &inst->winX, &inst->winY);
    int w, h;
    ::glfwGetFramebufferSize(inst->wnd.WindowHandle(), &w, &h);
    if (w < 0) w = 0;
    if (h < 0) h = 0;
    inst->winW = static_cast<unsigned int>(w);
    inst->winH = static_cast<unsigned int>(h);
}

void gl::ATWinBar::setWndValues(ATWinBar *inst) {
    int x, y;
    ::glfwGetFramebufferSize(inst->wnd.WindowHandle(), &x, &y);
    if (x < 0) x = 0;
    if (y < 0) y = 0;
    if ((static_cast<unsigned int>(x) != inst->winW) || (static_cast<unsigned int>(y) != inst->winH)) {
        ::glfwSetWindowSize(inst->wnd.WindowHandle(), inst->winW, inst->winH);
    }
    ::glfwGetWindowPos(inst->wnd.WindowHandle(), &x, &y);
    if ((x != inst->winX) || (y != inst->winY)) {
        ::glfwSetWindowPos(inst->wnd.WindowHandle(), inst->winX, inst->winY);
    }
    getWndValues(inst);
}

void gl::ATWinBar::setWinSizePreset(std::tuple<ATWinBar*, unsigned int, unsigned int> *preset) {
    ::glfwSetWindowSize(std::get<0>(*preset)->wnd.WindowHandle(), std::get<1>(*preset), std::get<2>(*preset));
    getWndValues(std::get<0>(*preset));
}

void gl::ATWinBar::toggleGUI(ATWinBar *inst) {
    inst->layer.ToggleEnable();
}

void gl::ATWinBar::setShowFPSinWindowTitle(const void *value, Window *wnd) {
    wnd->SetShowFPSinTitle(*(const bool*)value);
}

void gl::ATWinBar::getShowFPSinWindowTitle(void *value, Window *wnd) {
    *(bool*)value = wnd->ShowFPSinTitle();
}

void gl::ATWinBar::setShowSamplesinWindowTitle(const void *value, Window *wnd) {
    wnd->SetShowSamplesinTitle(*(const bool*)value);
}

void gl::ATWinBar::getShowSamplesinWindowTitle(void *value, Window *wnd) {
    *(bool*)value = wnd->ShowSamplesinTitle();
}

void gl::ATWinBar::setShowPrimsinWindowTitle(const void *value, Window *wnd) {
    wnd->SetShowPrimsinTitle(*(const bool*)value);
}

void gl::ATWinBar::getShowPrimsinWindowTitle(void *value, Window *wnd) {
    *(bool*)value = wnd->ShowPrimsinTitle();
}

void gl::ATWinBar::copyFPS(Window *wnd) {
    std::stringstream str;
    str << wnd->LiveFPS();
    ::glfwSetClipboardString(wnd->WindowHandle(), str.str().c_str());
}

void gl::ATWinBar::copyFPSList(Window *wnd) {
    std::stringstream str;
    for (float v : wnd->LiveFPSList()) {
        str << v << std::endl;
    }
    ::glfwSetClipboardString(wnd->WindowHandle(), str.str().c_str());
}

void gl::ATWinBar::setParamFilePath(const void *value, void *ctxt) {
    // Set: copy the value from AntTweakBar
    const char *src = *(const char **)(value);
    utility::ParamFileManager::Instance().filename = vislib::StringA(src);
}

void gl::ATWinBar::getParamFilePath(void *value, void *ctxt) {
    // Get: copy the value to AntTweakBar
    char **destPtr = (char **)value;
    TwCopyCDStringToLibrary(destPtr, vislib::StringA(utility::ParamFileManager::Instance().filename).PeekBuffer());
}

void gl::ATWinBar::loadParamFile(void *ctxt) {
    utility::ParamFileManager::Instance().Load();
}

void gl::ATWinBar::saveParamFile(void *ctxt) {
    utility::ParamFileManager::Instance().Save();
}
#endif
<commit_msg>ATWinBar: remove glfw function calls because no more gl::Window access<commit_after>/*
 * gl/ATWinBar.cpp
 *
 * Copyright (C) 2016 MegaMol Team
 * Alle Rechte vorbehalten.
 */
#include "stdafx.h"
#ifdef HAS_ANTTWEAKBAR
#include "gl/Window.h"
#include "gl/ATWinBar.h"
#include <sstream>
#include "GLFW/glfw3.h"
#include "gl/ATBUILayer.h"
#include "utility/ParamFileManager.h"

using namespace megamol;
using namespace megamol::console;

gl::ATWinBar::ATWinBar(ATBUILayer& layer, const char* wndName) : ATBar("winBar"), layer(layer),
        winX(0), winY(0), winW(0), winH(0), winSizePresets() {

    winSizePresets[0] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 256, 256);
    winSizePresets[1] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 512, 512);
    winSizePresets[2] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 1024, 1024);
    winSizePresets[3] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 1280, 720);
    winSizePresets[4] = std::tuple<ATWinBar*, unsigned int, unsigned int>(this, 1920, 1080);

    std::stringstream def;
    def << Name() << " "
        << "label='MegaMol - " << wndName << "' "
        << "help='Options regarding the Window and MegaMol Instance' "
        << "color='225 230 235' alpha='192' text='dark' "
        << "position='48 48' "
        << "size='256 256' valueswidth='128' ";
    ::TwDefine(def.str().c_str());

    // FPS
    ::TwAddVarRO(Handle(), "fps", TW_TYPE_FLOAT, &this->fps, "label='FPS' help='Rendering performance in frames per second, measured by the time between OpenGL buffer swaps. This value is the mean over several rendering calls or over the rendering calls within some time'");
    ::TwAddVarCB(Handle(), "fpsTitle", TW_TYPE_BOOLCPP,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setShowFPSinWindowTitle),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getShowFPSinWindowTitle),
        nullptr, "label='Show FPS in Window Caption'");
    ::TwAddVarCB(Handle(), "sampTitle", TW_TYPE_BOOLCPP,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setShowSamplesinWindowTitle),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getShowSamplesinWindowTitle),
        nullptr, "label='Show Samples passed in Window Caption'");
    ::TwAddVarCB(Handle(), "primsTitle", TW_TYPE_BOOLCPP,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setShowPrimsinWindowTitle),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getShowPrimsinWindowTitle),
        nullptr, "label='Show Primitives generated in Window Caption'");
    ::TwAddButton(Handle(), "fpsCopy", reinterpret_cast<TwButtonCallback>(&ATWinBar::copyFPS), nullptr, "label='Copy to Clipboard'");
    ::TwAddButton(Handle(), "fpsCopyList", reinterpret_cast<TwButtonCallback>(&ATWinBar::copyFPSList), nullptr, "label='Copy FPS List to Clipboard'");

    // Window placement, size, decorations, etc.
    //  Note: switching to/from fullscreen mode is no longer supported, as GLFW cannot remove/add window decorations after window was created.
    ::TwAddVarRW(Handle(), "winX", TW_TYPE_INT32, &winX, "label='Left' group='Window'");
    ::TwAddVarRW(Handle(), "winY", TW_TYPE_INT32, &winY, "label='Top' group='Window'");
    ::TwAddVarRW(Handle(), "winW", TW_TYPE_UINT32, &winW, "label='Width' group='Window'");
    ::TwAddVarRW(Handle(), "winH", TW_TYPE_UINT32, &winH, "label='Height' group='Window'");
    ::TwAddSeparator(Handle(), nullptr, "group='Window'");
    getWndValues(this);

    ::TwAddButton(Handle(), "winValGet", reinterpret_cast<TwButtonCallback>(&ATWinBar::getWndValues), this, "label='Get Values' group='Window'");
    ::TwAddButton(Handle(), "winValSet", reinterpret_cast<TwButtonCallback>(&ATWinBar::setWndValues), this, "label='Set Values' group='Window'");

    unsigned int i = 0;
    for (auto& wsp : winSizePresets) {
        def.str("");
        def << "winSizePreset" << i;
        std::string name = def.str();
        def.str("");
        def << "label='Set Size " << std::get<1>(wsp) << "x" << std::get<2>(wsp) << "' group='WinSizePre'";
        ::TwAddButton(Handle(), name.c_str(), reinterpret_cast<TwButtonCallback>(&ATWinBar::setWinSizePreset), &wsp, def.str().c_str());
        ++i;
    }
    def.str("");
    def << Name() << "/WinSizePre "
        << "label='Size Presets' "
        << "group='Window' "
        << "opened=true ";
    ::TwDefine(def.str().c_str());
    def.str("");
    def << Name() << "/Window "
        << "opened=false ";
    ::TwDefine(def.str().c_str());

    // GUI show/hide control
    ::TwAddButton(Handle(), "hideGUI", reinterpret_cast<TwButtonCallback>(&ATWinBar::toggleGUI), this, "label='Hide/Show GUI' key=F12");

    // ParamFile
    ::TwAddVarCB(Handle(), "paramFilePath", TW_TYPE_CDSTRING,
        reinterpret_cast<TwSetVarCallback>(&ATWinBar::setParamFilePath),
        reinterpret_cast<TwGetVarCallback>(&ATWinBar::getParamFilePath),
        nullptr, "label='ParamFile' group='paramFile'");
    ::TwAddButton(Handle(), "loadParamFile", reinterpret_cast<TwButtonCallback>(&ATWinBar::loadParamFile), nullptr, "label='Load ParamFile' group='paramFile'");
    ::TwAddButton(Handle(), "saveParamFile", reinterpret_cast<TwButtonCallback>(&ATWinBar::saveParamFile), nullptr, "label='Save ParamFile' group='paramFile'");
    def.str("");
    def << Name() << "/paramFile "
        << "label='ParamFile' "
        << "opened=true ";
    ::TwDefine(def.str().c_str());

    // (later: ProjectFile)

    def.str("");
    def << Name() << " "
        << "iconified=true ";
    ::TwDefine(def.str().c_str());

}

gl::ATWinBar::~ATWinBar() {
}

void gl::ATWinBar::getWndValues(ATWinBar *inst) {
//    ::glfwGetWindowPos(inst->wnd.WindowHandle(), &inst->winX, &inst->winY);
//    int w, h;
//    ::glfwGetFramebufferSize(inst->wnd.WindowHandle(), &w, &h);
//    if (w < 0) w = 0;
//    if (h < 0) h = 0;
//    inst->winW = static_cast<unsigned int>(w);
//    inst->winH = static_cast<unsigned int>(h);
}

void gl::ATWinBar::setWndValues(ATWinBar *inst) {
//    int x, y;
//    ::glfwGetFramebufferSize(inst->wnd.WindowHandle(), &x, &y);
//    if (x < 0) x = 0;
//    if (y < 0) y = 0;
//    if ((static_cast<unsigned int>(x) != inst->winW) || (static_cast<unsigned int>(y) != inst->winH)) {
//        ::glfwSetWindowSize(inst->wnd.WindowHandle(), inst->winW, inst->winH);
//    }
//    ::glfwGetWindowPos(inst->wnd.WindowHandle(), &x, &y);
//    if ((x != inst->winX) || (y != inst->winY)) {
//        ::glfwSetWindowPos(inst->wnd.WindowHandle(), inst->winX, inst->winY);
//    }
//    getWndValues(inst);
}

void gl::ATWinBar::setWinSizePreset(std::tuple<ATWinBar*, unsigned int, unsigned int> *preset) {
//    ::glfwSetWindowSize(std::get<0>(*preset)->wnd.WindowHandle(), std::get<1>(*preset), std::get<2>(*preset));
//    getWndValues(std::get<0>(*preset));
}

void gl::ATWinBar::toggleGUI(ATWinBar *inst) {
    inst->layer.ToggleEnable();
}

void gl::ATWinBar::setShowFPSinWindowTitle(const void *value, Window *wnd) {
    //wnd->SetShowFPSinTitle(*(const bool*)value);
}

void gl::ATWinBar::getShowFPSinWindowTitle(void *value, Window *wnd) {
    //*(bool*)value = wnd->ShowFPSinTitle();
}

void gl::ATWinBar::setShowSamplesinWindowTitle(const void *value, Window *wnd) {
    //wnd->SetShowSamplesinTitle(*(const bool*)value);
}

void gl::ATWinBar::getShowSamplesinWindowTitle(void *value, Window *wnd) {
    //*(bool*)value = wnd->ShowSamplesinTitle();
}

void gl::ATWinBar::setShowPrimsinWindowTitle(const void *value, Window *wnd) {
    //wnd->SetShowPrimsinTitle(*(const bool*)value);
}

void gl::ATWinBar::getShowPrimsinWindowTitle(void *value, Window *wnd) {
    //*(bool*)value = wnd->ShowPrimsinTitle();
}

void gl::ATWinBar::copyFPS(Window *wnd) {
    std::stringstream str;
    //str << wnd->LiveFPS();
    //::glfwSetClipboardString(wnd->WindowHandle(), str.str().c_str());
}

void gl::ATWinBar::copyFPSList(Window *wnd) {
    std::stringstream str;
    //for (float v : wnd->LiveFPSList()) {
        //str << v << std::endl;
    //}
    //::glfwSetClipboardString(wnd->WindowHandle(), str.str().c_str());
}

void gl::ATWinBar::setParamFilePath(const void *value, void *ctxt) {
    // Set: copy the value from AntTweakBar
    const char *src = *(const char **)(value);
    utility::ParamFileManager::Instance().filename = vislib::StringA(src);
}

void gl::ATWinBar::getParamFilePath(void *value, void *ctxt) {
    // Get: copy the value to AntTweakBar
    char **destPtr = (char **)value;
    TwCopyCDStringToLibrary(destPtr, vislib::StringA(utility::ParamFileManager::Instance().filename).PeekBuffer());
}

void gl::ATWinBar::loadParamFile(void *ctxt) {
    utility::ParamFileManager::Instance().Load();
}

void gl::ATWinBar::saveParamFile(void *ctxt) {
    utility::ParamFileManager::Instance().Save();
}
#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2016 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dPrintf(fmt, arg...) __dPrintf(DBG_STATS, "(%s) " fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
{
	dPrintf("(%s)", parent);
}

stats::~stats()
{
	dPrintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dPrintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dPrintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = ((uint64_t)pcr[0] * 0x2000000) +
		    ((uint64_t)pcr[1] * 0x20000) +
		    ((uint64_t)pcr[2] * 0x200) +
		    ((uint64_t)pcr[3] * 0x02) +
		    ((uint64_t)(pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { (void)p; return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
#if 0
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
#if 0
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		dPrintf("pid %04x %5" PRIu64 " p%s  %sb%s  %sbit",
			iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		dPrintf("pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if (tei_count) dPrintf("tei count: %" PRIu64 " (%" PRIu64 "%%)", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	return parse(p, pkt_stats, hdr, adapt);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats, pkt_hdr_t &hdr, adaptation_field_t &adapt)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		memset(&adapt, 0, sizeof(adapt));
		memset(&hdr, 0, sizeof(hdr));

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats, hdr, adapt);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dPrintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			dPrintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);

#if DBG
			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				__log_printf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			dPrintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dPrintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<commit_msg>stats: fix build warnings<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2016 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dPrintf(fmt, arg...) __dPrintf(DBG_STATS, "(%s) " fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
{
	dPrintf("(%s)", parent);
}

stats::~stats()
{
	dPrintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dPrintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dPrintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = ((uint64_t)pcr[0] * 0x2000000) +
		    ((uint64_t)pcr[1] * 0x20000) +
		    ((uint64_t)pcr[2] * 0x200) +
		    ((uint64_t)pcr[3] * 0x02) +
		    ((uint64_t)(pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { (void)p; return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
#if 0
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
#if 0
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		__log_printf(stderr, "pid %04x %5" PRIu64 " p%s  %sb%s  %sbit",
			     iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			     stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			     stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		__log_printf(stderr, "pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if (tei_count) __log_printf(stderr, "tei count: %" PRIu64 " (%" PRIu64 "%%)", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	return parse(p, pkt_stats, hdr, adapt);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats, pkt_hdr_t &hdr, adaptation_field_t &adapt)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		memset(&adapt, 0, sizeof(adapt));
		memset(&hdr, 0, sizeof(hdr));

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats, hdr, adapt);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dPrintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			__log_printf(stderr, "PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);

#if DBG
			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				__log_printf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			__log_printf(stderr, "PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dPrintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<|endoftext|>