<commit_before><?hh

namespace LotGD\Census;

use LotGD\Census\WarriorsPageState;

class Census {
  public bool $debugFakeData = false;
  public bool $debugLocalOnly = false;
  public Repository $repo;

  public Logger $logger;

  public function __construct(\Monolog\Logger $logger) {
    $this->logger = $logger;
    $this->repo = new Repository($this->logger);
  }

  public function readCommandLineArguments(array $argv, int $argc) {
    for ($i = 1; $i < $argc; $i++) {
      $a = $argv[$i];

      if ($a == '--local-only') {
        $this->debugLocalOnly = true;
        continue;
      }
      if ($a == '--fake-data') {
        $this->debugFakeData = true;
        continue;
      }
      if ($a == '--debug') {
        $this->logger->setHandlers(array(new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::DEBUG)));
        continue;
      }

      echo "Invalid argument: {$a}", PHP_EOL;
      exit(1);
    }
  }

  public static function main(array $argv, int $argc) {
    $listURL = '/list.php?op=bypage&page=';

    $l = new \Monolog\Logger('census');
    $l->pushHandler(new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::WARNING));

    $c = new Census($l);
    $c->readCommandLineArguments($argv, $argc);

    $statsMap = Map {};

    if ($c->debugFakeData) {
      $sites = Vector {};

      $stats = new Stats();
      $stats->count = 103;
      $stats->dau = 12;
      $stats->mau = 23;
      $statsMap['site3'] = $stats;

      $stats = new Stats();
      $stats->count = 123;
      $stats->dau = 3;
      $stats->mau = 13;
      $statsMap['twx.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 400;
      $stats->dau = 126;
      $stats->mau = 316;
      $statsMap['www.lotgd.net'] = $stats;

      $stats = new Stats();
      $stats->count = 594;
      $stats->dau = 33;
      $stats->mau = 135;
      $statsMap['www.dragonsofmyth.com'] = $stats;

      $stats = new Stats();
      $stats->count = 270;
      $stats->dau = 8;
      $stats->mau = 25;
      $statsMap['stormvalley.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 29;
      $stats->dau = 1;
      $stats->mau = 10;
      $statsMap['dragonprimelogd.net'] = $stats;

      $stats = new Stats();
      $stats->count = 586;
      $stats->dau = 80;
      $stats->mau = 274;
      $statsMap['forbiddenrealm.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 94;
      $stats->dau = 6;
      $stats->mau = 36;
      $statsMap['enchantedland.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 7;
      $stats->dau = 0;
      $stats->mau = 0;
      $statsMap['twx.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 30;
      $stats->dau = 3;
      $stats->mau = 7;
      $statsMap['ess.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 395;
      $stats->dau = 66;
      $stats->mau = 214;
      $statsMap['lotgd4adults2.com'] = $stats;

      $stats = new Stats();
      $stats->count = 43;
      $stats->dau = 19;
      $stats->mau = 43;
      $statsMap['deathstar.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 20;
      $stats->dau = 0;
      $stats->mau = 6;
      $statsMap['golden-empire.com'] = $stats;

      $stats = new Stats();
      $stats->count = 632;
      $stats->dau = 191;
      $stats->mau = 444;
      $statsMap['the-complex.net'] = $stats;

      $stats = new Stats();
      $stats->count = 54;
      $stats->dau = 12;
      $stats->mau = 38;
      $statsMap['tynastera2.com'] = $stats;

      $stats = new Stats();
      $stats->count = 1494;
      $stats->dau = 308;
      $stats->mau = 705;
      $statsMap['www.lotgd.de'] = $stats;
    } else {
      $sites = $c->repo->getSites();

      foreach ($sites as $site) {
        $stats = new Stats();

        $i = 1;
        while ($contents = file_get_contents($u = 'http://' . $site . $listURL . $i)) {
          if ($i > 100) {
            $c->logger->addError("  too many pages");
            break;
          }

          $c->logger->addDebug("Fetching {$u}");
          $wp = new WarriorsPage($c->logger, $u, $contents);

          if ($wp->stats != null) {
            $stats->add($wp->stats);
          }
          if ($wp->state == WarriorsPageState::End || $wp->state == WarriorsPageState::Error) {
            break;
          }

          $i++;
        }

        $statsMap[$site] = $stats;
      }
    }

    $c->logger->addDebug('Sites data:');
    $c->logger->addDebug(var_export($statsMap, true));

    $c->updateReadme($statsMap);

    $c->updateCSV('data/total.csv', $statsMap->map(function (Stats $s) : int {
      return $s->count;
    }));

    $c->updateCSV('data/mau.csv', $statsMap->map(function (Stats $s) : int {
      return $s->mau;
    }));

    $c->updateCSV('data/dau.csv', $statsMap->map(function (Stats $s) : int {
      return $s->dau;
    }));
  }

  private function updateCSV(string $file, Map<string, int> $map) {
    $localFilePath = __DIR__ . '/../../' . $file;
    if ($this->debugLocalOnly) {
      $contents = file_get_contents($localFilePath);
    } else {
      $contents = $this->repo->getFile($file);
    }

    if ($contents === null) {
      $this->logger->addError("Couldn't get {$file} from the repo.");
      return;
    }

    $csv = new CSV($this->logger, $file, $contents);
    $csv->appendToRows($map);
    $result = $csv->contents();

    $this->logger->addDebug("Writing {$file}:");
    $this->logger->addDebug($result);
    if ($this->debugLocalOnly) {
      file_put_contents($localFilePath, $result);
    } else {
      $this->repo->updateFile($file, $contents, 'The latest data.');
    }
  }

  private function updateReadme(Map<string, Stats> $statsMap) {
    $localTemplateFilePath = __DIR__ . '/../../templates/README.md';
    $localReadmeFilePath = __DIR__ . '/../../README.md';

    // Sort the map by total user count.
    $statsArray = $statsMap->toArray();
    uasort($statsArray, 'Stats::compare');

    if ($this->debugLocalOnly) {
      $readme = file_get_contents($localTemplateFilePath);
    } else {
      $readme = $this->repo->getFile('templates/README.md');
    }

    $readme .= "Site | Total | MAU | DAU\n";
    $readme .= "--- | ---:| ---:| ---:\n";

    foreach ($statsArray as $s => $stats) {
      $count = $stats->count;
      $mau = $stats->mau;
      $dau = $stats->dau;
      $readme .= "[$s](http://{$s})|{$count}|{$mau}|{$dau}\n";
    }

    $readme .= "\nAs of " . date("F j, Y") . ".\n";

    // Write the README.md with the latest data.
    $this->logger->addDebug("Writing README.md:");
    $this->logger->addDebug($readme);
    if ($this->debugLocalOnly) {
      file_put_contents($localReadmeFilePath, $readme);
    } else {
      $this->repo->updateFile('README.md', $readme, 'The latest data.');
    }
  }
}
<commit_msg>Fixing dumb bug in CSV committing code, lolz<commit_after><?hh

namespace LotGD\Census;

use LotGD\Census\WarriorsPageState;

class Census {
  public bool $debugFakeData = false;
  public bool $debugLocalOnly = false;
  public Repository $repo;

  public Logger $logger;

  public function __construct(\Monolog\Logger $logger) {
    $this->logger = $logger;
    $this->repo = new Repository($this->logger);
  }

  public function readCommandLineArguments(array $argv, int $argc) {
    for ($i = 1; $i < $argc; $i++) {
      $a = $argv[$i];

      if ($a == '--local-only') {
        $this->debugLocalOnly = true;
        continue;
      }
      if ($a == '--fake-data') {
        $this->debugFakeData = true;
        continue;
      }
      if ($a == '--debug') {
        $this->logger->setHandlers(array(new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::DEBUG)));
        continue;
      }

      echo "Invalid argument: {$a}", PHP_EOL;
      exit(1);
    }
  }

  public static function main(array $argv, int $argc) {
    $listURL = '/list.php?op=bypage&page=';

    $l = new \Monolog\Logger('census');
    $l->pushHandler(new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::WARNING));

    $c = new Census($l);
    $c->readCommandLineArguments($argv, $argc);

    $statsMap = Map {};

    if ($c->debugFakeData) {
      $sites = Vector {};

      $stats = new Stats();
      $stats->count = 103;
      $stats->dau = 12;
      $stats->mau = 23;
      $statsMap['site3'] = $stats;

      $stats = new Stats();
      $stats->count = 123;
      $stats->dau = 3;
      $stats->mau = 13;
      $statsMap['twx.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 400;
      $stats->dau = 126;
      $stats->mau = 316;
      $statsMap['www.lotgd.net'] = $stats;

      $stats = new Stats();
      $stats->count = 594;
      $stats->dau = 33;
      $stats->mau = 135;
      $statsMap['www.dragonsofmyth.com'] = $stats;

      $stats = new Stats();
      $stats->count = 270;
      $stats->dau = 8;
      $stats->mau = 25;
      $statsMap['stormvalley.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 29;
      $stats->dau = 1;
      $stats->mau = 10;
      $statsMap['dragonprimelogd.net'] = $stats;

      $stats = new Stats();
      $stats->count = 586;
      $stats->dau = 80;
      $stats->mau = 274;
      $statsMap['forbiddenrealm.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 94;
      $stats->dau = 6;
      $stats->mau = 36;
      $statsMap['enchantedland.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 7;
      $stats->dau = 0;
      $stats->mau = 0;
      $statsMap['twx.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 30;
      $stats->dau = 3;
      $stats->mau = 7;
      $statsMap['ess.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 395;
      $stats->dau = 66;
      $stats->mau = 214;
      $statsMap['lotgd4adults2.com'] = $stats;

      $stats = new Stats();
      $stats->count = 43;
      $stats->dau = 19;
      $stats->mau = 43;
      $statsMap['deathstar.rpglink.in'] = $stats;

      $stats = new Stats();
      $stats->count = 20;
      $stats->dau = 0;
      $stats->mau = 6;
      $statsMap['golden-empire.com'] = $stats;

      $stats = new Stats();
      $stats->count = 632;
      $stats->dau = 191;
      $stats->mau = 444;
      $statsMap['the-complex.net'] = $stats;

      $stats = new Stats();
      $stats->count = 54;
      $stats->dau = 12;
      $stats->mau = 38;
      $statsMap['tynastera2.com'] = $stats;

      $stats = new Stats();
      $stats->count = 1494;
      $stats->dau = 308;
      $stats->mau = 705;
      $statsMap['www.lotgd.de'] = $stats;
    } else {
      $sites = $c->repo->getSites();

      foreach ($sites as $site) {
        $stats = new Stats();

        $i = 1;
        while ($contents = file_get_contents($u = 'http://' . $site . $listURL . $i)) {
          if ($i > 100) {
            $c->logger->addError("  too many pages");
            break;
          }

          $c->logger->addDebug("Fetching {$u}");
          $wp = new WarriorsPage($c->logger, $u, $contents);

          if ($wp->stats != null) {
            $stats->add($wp->stats);
          }
          if ($wp->state == WarriorsPageState::End || $wp->state == WarriorsPageState::Error) {
            break;
          }

          $i++;
        }

        $statsMap[$site] = $stats;
      }
    }

    $c->logger->addDebug('Sites data:');
    $c->logger->addDebug(var_export($statsMap, true));

    $c->updateReadme($statsMap);

    $c->updateCSV('data/total.csv', $statsMap->map(function (Stats $s) : int {
      return $s->count;
    }));

    $c->updateCSV('data/mau.csv', $statsMap->map(function (Stats $s) : int {
      return $s->mau;
    }));

    $c->updateCSV('data/dau.csv', $statsMap->map(function (Stats $s) : int {
      return $s->dau;
    }));
  }

  private function updateCSV(string $file, Map<string, int> $map) {
    $localFilePath = __DIR__ . '/../../' . $file;
    if ($this->debugLocalOnly) {
      $contents = file_get_contents($localFilePath);
    } else {
      $contents = $this->repo->getFile($file);
    }

    if ($contents === null) {
      $this->logger->addError("Couldn't get {$file} from the repo.");
      return;
    }

    $csv = new CSV($this->logger, $file, $contents);
    $csv->appendToRows($map);
    $result = $csv->contents();

    $this->logger->addDebug("Writing {$file}:");
    $this->logger->addDebug($result);
    if ($this->debugLocalOnly) {
      file_put_contents($localFilePath, $result);
    } else {
      $this->repo->updateFile($file, $result, 'The latest data.');
    }
  }

  private function updateReadme(Map<string, Stats> $statsMap) {
    $localTemplateFilePath = __DIR__ . '/../../templates/README.md';
    $localReadmeFilePath = __DIR__ . '/../../README.md';

    // Sort the map by total user count.
    $statsArray = $statsMap->toArray();
    uasort($statsArray, 'Stats::compare');

    if ($this->debugLocalOnly) {
      $readme = file_get_contents($localTemplateFilePath);
    } else {
      $readme = $this->repo->getFile('templates/README.md');
    }

    $readme .= "Site | Total | MAU | DAU\n";
    $readme .= "--- | ---:| ---:| ---:\n";

    foreach ($statsArray as $s => $stats) {
      $count = $stats->count;
      $mau = $stats->mau;
      $dau = $stats->dau;
      $readme .= "[$s](http://{$s})|{$count}|{$mau}|{$dau}\n";
    }

    $readme .= "\nAs of " . date("F j, Y") . ".\n";

    // Write the README.md with the latest data.
    $this->logger->addDebug("Writing README.md:");
    $this->logger->addDebug($readme);
    if ($this->debugLocalOnly) {
      file_put_contents($localReadmeFilePath, $readme);
    } else {
      $this->repo->updateFile('README.md', $readme, 'The latest data.');
    }
  }
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/InterpreterCallbacks.h"

#include "cling/Interpreter/Interpreter.h"

#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTDeserializationListener.h"

using namespace clang;

namespace cling {

  ///\brief Translates 'interesting' for the interpreter
  /// ASTDeserializationListener events into interpreter callback.
  ///
  class InterpreterDeserializationListener : public ASTDeserializationListener {
  private:
    cling::InterpreterCallbacks* m_Callbacks;
  public:
    InterpreterDeserializationListener(InterpreterCallbacks* C)
      : m_Callbacks(C) {}

    virtual void DeclRead(serialization::DeclID, const Decl *D) {
      if (m_Callbacks)
        m_Callbacks->DeclDeserialized(D);
    }
    virtual void TypeRead(serialization::TypeIdx, QualType T) {
      if (m_Callbacks)
        m_Callbacks->TypeDeserialized(T.getTypePtr());
    }
  };

  ///\brief Translates 'interesting' for the interpreter ExternalSemaSource
  /// events into interpreter callbacks.
  ///
  class InterpreterExternalSemaSource : public clang::ExternalSemaSource {
  protected:
    ///\brief The interpreter callback which are subscribed for the events.
    ///
    /// Usually the callbacks is the owner of the class and the interpreter owns
    /// the callbacks so they can't be out of sync. Eg we notifying the wrong
    /// callback class.
    ///
    InterpreterCallbacks* m_Callbacks; // we don't own it.

  public:
    InterpreterExternalSemaSource(InterpreterCallbacks* C) : m_Callbacks(C){}

    ~InterpreterExternalSemaSource() {}

    InterpreterCallbacks* getCallbacks() const { return m_Callbacks; }

    /// \brief Provides last resort lookup for failed unqualified lookups.
    ///
    /// This gets translated into InterpreterCallback's call.
    ///
    ///\param[out] R The recovered symbol.
    ///\param[in] S The scope in which the lookup failed.
    ///
    ///\returns true if a suitable declaration is found.
    ///
    virtual bool LookupUnqualified(clang::LookupResult& R, clang::Scope* S) {
      if (m_Callbacks)
        return m_Callbacks->LookupObject(R, S);

      return false;
    }

    virtual bool FindExternalVisibleDeclsByName(const clang::DeclContext* DC,
                                                clang::DeclarationName Name) {
      if (m_Callbacks)
        return m_Callbacks->LookupObject(DC, Name);

      return false;
    }

    void UpdateWithNewDeclsFwd(const DeclContext *DC, DeclarationName Name,
                               llvm::ArrayRef<NamedDecl*> Decls) {
      SetExternalVisibleDeclsForName(DC, Name, Decls);
    }
  };

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                                            InterpreterExternalSemaSource* IESS,
                                        InterpreterDeserializationListener* IDL)
    : m_Interpreter(interp),  m_ExternalSemaSource(IESS), m_IsRuntime(false),
      m_DeserializationListener(IDL) {
    if (IESS)
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager();
    if (IDL && Reader)
      Reader->setDeserializationListener(IDL);
  }

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                             bool enableExternalSemaSourceCallbacks/* = false*/,
                       bool enableDeserializationListenerCallbacks/* = false*/)
    : m_Interpreter(interp), m_IsRuntime(false) {

    if (enableExternalSemaSourceCallbacks) {
      m_ExternalSemaSource.reset(new InterpreterExternalSemaSource(this));
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    }

    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager();
    if (enableDeserializationListenerCallbacks && Reader) {
      // FIXME: need to create a multiplexer if a DeserializationListener is
      // alreday present.
      m_DeserializationListener.
        reset(new InterpreterDeserializationListener(this));
      Reader->setDeserializationListener(m_DeserializationListener.get());
    }
  }

  // pin the vtable here
  InterpreterCallbacks::~InterpreterCallbacks() {
    // FIXME: we have to remove the external source at destruction time. Needs
    // further tweaks of the patch in clang. This will be done later once the
    // patch is in clang's mainline.
  }

  ExternalSemaSource*
  InterpreterCallbacks::getInterpreterExternalSemaSource() const {
    return m_ExternalSemaSource.get();
  }

  ASTDeserializationListener*
  InterpreterCallbacks::getInterpreterDeserializationListener() const {
    return m_DeserializationListener.get();
  }

  bool InterpreterCallbacks::LookupObject(LookupResult&, Scope*) {
    return false;
  }

  bool InterpreterCallbacks::LookupObject(const DeclContext*, DeclarationName) {
    return false;
  }

  void InterpreterCallbacks::UpdateWithNewDecls(const DeclContext *DC,
                                                DeclarationName Name,
                                             llvm::ArrayRef<NamedDecl*> Decls) {
    if (m_ExternalSemaSource)
      m_ExternalSemaSource->UpdateWithNewDeclsFwd(DC, Name, Decls);
  }
} // end namespace cling

// TODO: Make the build system in the testsuite aware how to build that class
// and extract it out there again.
#include "DynamicLookup.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
namespace cling {
namespace test {
  TestProxy* Tester = 0;

  extern "C" int printf(const char* fmt, ...);
  TestProxy::TestProxy(){}
  int TestProxy::Draw(){ return 12; }
  const char* TestProxy::getVersion(){ return "Interpreter.cpp"; }

  int TestProxy::Add10(int num) { return num + 10;}

  int TestProxy::Add(int a, int b) {
    return a + b;
  }

  void TestProxy::PrintString(std::string s) { printf("%s\n", s.c_str()); }

  bool TestProxy::PrintArray(int a[], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      printf("%i", a[i]);

    printf("%s", "\n");

    return true;
  }

  void TestProxy::PrintArray(float a[][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 5; ++j)
        printf("%i", (int)a[i][j]);

    printf("%s", "\n");
  }

  void TestProxy::PrintArray(int a[][4][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 4; ++j)
        for (unsigned k = 0; k < 5; ++k)
          printf("%i", a[i][j][k]);

    printf("%s", "\n");
  }

  SymbolResolverCallback::SymbolResolverCallback(Interpreter* interp)
    : InterpreterCallbacks(interp), m_TesterDecl(0) {
    m_Interpreter->process("cling::test::Tester = new cling::test::TestProxy();");
  }

  SymbolResolverCallback::~SymbolResolverCallback() { }

  bool SymbolResolverCallback::LookupObject(LookupResult& R, Scope* S) {
    if (m_IsRuntime) {
      // Only for demo resolve all unknown objects to cling::test::Tester
      if (!m_TesterDecl) {
        clang::Sema& SemaR = m_Interpreter->getSema();
        clang::NamespaceDecl* NSD = utils::Lookup::Namespace(&SemaR, "cling");
        NSD = utils::Lookup::Namespace(&SemaR, "test", NSD);
        m_TesterDecl = utils::Lookup::Named(&SemaR, "Tester", NSD);
      }
      assert (m_TesterDecl && "Tester not found!");
      R.addDecl(m_TesterDecl);
      return true; // Tell clang to continue.
    }

    if (ShouldResolveAtRuntime(R, S)) {
      ASTContext& C = R.getSema().getASTContext();
      DeclContext* DC = 0;
      // For DeclContext-less scopes like if (dyn_expr) {}
      while (!DC) {
        DC = static_cast<DeclContext*>(S->getEntity());
        S = S->getParent();
      }
      DeclarationName Name = R.getLookupName();
      IdentifierInfo* II = Name.getAsIdentifierInfo();
      SourceLocation Loc = R.getNameLoc();
      VarDecl* Res = VarDecl::Create(C, DC, Loc, Loc, II, C.DependentTy,
                                     /*TypeSourceInfo*/0, SC_None);

      // Annotate the decl to give a hint in cling. FIXME: Current implementation
      // is a gross hack, because TClingCallbacks shouldn't know about
      // EvaluateTSynthesizer at all!
      SourceRange invalidRange;
      Res->addAttr(new (C) AnnotateAttr(invalidRange, C, "__ResolveAtRuntime"));
      R.addDecl(Res);
      DC->addDecl(Res);
      // Say that we can handle the situation. Clang should try to recover
      return true;
    }

    return false;
  }

  bool SymbolResolverCallback::ShouldResolveAtRuntime(LookupResult& R,
                                                      Scope* S) {

    if (R.getLookupKind() != Sema::LookupOrdinaryName)
      return false;

    if (R.isForRedeclaration())
      return false;

    if (!R.empty())
      return false;

    // FIXME: Figure out better way to handle:
    // C++ [basic.lookup.classref]p1:
    //   In a class member access expression (5.2.5), if the . or -> token is
    //   immediately followed by an identifier followed by a <, the
    //   identifier must be looked up to determine whether the < is the
    //   beginning of a template argument list (14.2) or a less-than operator.
    //   The identifier is first looked up in the class of the object
    //   expression. If the identifier is not found, it is then looked up in
    //   the context of the entire postfix-expression and shall name a class
    //   or function template.
    //
    // We want to ignore object(.|->)member<template>
    if (R.getSema().PP.LookAhead(0).getKind() == tok::less)
      // TODO: check for . or -> in the cached token stream
      return false;

    for (Scope* DepScope = S; DepScope; DepScope = DepScope->getParent()) {
      if (DeclContext* Ctx = static_cast<DeclContext*>(DepScope->getEntity())) {
        if (!Ctx->isDependentContext())
          // For now we support only the prompt.
          if (isa<FunctionDecl>(Ctx))
            return true;
      }
    }

    return false;
  }

} // end test
} // end cling
<commit_msg>Subscribe to the interesting events.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/InterpreterCallbacks.h"

#include "cling/Interpreter/Interpreter.h"

#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTDeserializationListener.h"

using namespace clang;

namespace cling {

  ///\brief Translates 'interesting' for the interpreter
  /// ASTDeserializationListener events into interpreter callback.
  ///
  class InterpreterDeserializationListener : public ASTDeserializationListener {
  private:
    cling::InterpreterCallbacks* m_Callbacks;
  public:
    InterpreterDeserializationListener(InterpreterCallbacks* C)
      : m_Callbacks(C) {}

    virtual void DeclRead(serialization::DeclID, const Decl *D) {
      if (m_Callbacks)
        m_Callbacks->DeclDeserialized(D);
    }
    virtual void TypeRead(serialization::TypeIdx, QualType T) {
      if (m_Callbacks)
        m_Callbacks->TypeDeserialized(T.getTypePtr());
    }
  };

  ///\brief Translates 'interesting' for the interpreter ExternalSemaSource
  /// events into interpreter callbacks.
  ///
  class InterpreterExternalSemaSource : public clang::ExternalSemaSource {
  protected:
    ///\brief The interpreter callback which are subscribed for the events.
    ///
    /// Usually the callbacks is the owner of the class and the interpreter owns
    /// the callbacks so they can't be out of sync. Eg we notifying the wrong
    /// callback class.
    ///
    InterpreterCallbacks* m_Callbacks; // we don't own it.

  public:
    InterpreterExternalSemaSource(InterpreterCallbacks* C) : m_Callbacks(C){}

    ~InterpreterExternalSemaSource() {}

    InterpreterCallbacks* getCallbacks() const { return m_Callbacks; }

    /// \brief Provides last resort lookup for failed unqualified lookups.
    ///
    /// This gets translated into InterpreterCallback's call.
    ///
    ///\param[out] R The recovered symbol.
    ///\param[in] S The scope in which the lookup failed.
    ///
    ///\returns true if a suitable declaration is found.
    ///
    virtual bool LookupUnqualified(clang::LookupResult& R, clang::Scope* S) {
      if (m_Callbacks)
        return m_Callbacks->LookupObject(R, S);

      return false;
    }

    virtual bool FindExternalVisibleDeclsByName(const clang::DeclContext* DC,
                                                clang::DeclarationName Name) {
      if (m_Callbacks)
        return m_Callbacks->LookupObject(DC, Name);

      return false;
    }

    void UpdateWithNewDeclsFwd(const DeclContext *DC, DeclarationName Name,
                               llvm::ArrayRef<NamedDecl*> Decls) {
      SetExternalVisibleDeclsForName(DC, Name, Decls);
    }
  };

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                                            InterpreterExternalSemaSource* IESS,
                                        InterpreterDeserializationListener* IDL)
    : m_Interpreter(interp),  m_ExternalSemaSource(IESS), m_IsRuntime(false),
      m_DeserializationListener(IDL) {
    if (IESS)
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager();
    if (IDL && Reader)
      Reader->setDeserializationListener(IDL);
  }

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                             bool enableExternalSemaSourceCallbacks/* = false*/,
                       bool enableDeserializationListenerCallbacks/* = false*/)
    : m_Interpreter(interp), m_IsRuntime(false) {

    if (enableExternalSemaSourceCallbacks) {
      m_ExternalSemaSource.reset(new InterpreterExternalSemaSource(this));
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    }

    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager();
    if (enableDeserializationListenerCallbacks && Reader) {
      // FIXME: need to create a multiplexer if a DeserializationListener is
      // alreday present.
      m_DeserializationListener.
        reset(new InterpreterDeserializationListener(this));
      Reader->setDeserializationListener(m_DeserializationListener.get());
    }
  }

  // pin the vtable here
  InterpreterCallbacks::~InterpreterCallbacks() {
    // FIXME: we have to remove the external source at destruction time. Needs
    // further tweaks of the patch in clang. This will be done later once the
    // patch is in clang's mainline.
  }

  ExternalSemaSource*
  InterpreterCallbacks::getInterpreterExternalSemaSource() const {
    return m_ExternalSemaSource.get();
  }

  ASTDeserializationListener*
  InterpreterCallbacks::getInterpreterDeserializationListener() const {
    return m_DeserializationListener.get();
  }

  bool InterpreterCallbacks::LookupObject(LookupResult&, Scope*) {
    return false;
  }

  bool InterpreterCallbacks::LookupObject(const DeclContext*, DeclarationName) {
    return false;
  }

  void InterpreterCallbacks::UpdateWithNewDecls(const DeclContext *DC,
                                                DeclarationName Name,
                                             llvm::ArrayRef<NamedDecl*> Decls) {
    if (m_ExternalSemaSource)
      m_ExternalSemaSource->UpdateWithNewDeclsFwd(DC, Name, Decls);
  }
} // end namespace cling

// TODO: Make the build system in the testsuite aware how to build that class
// and extract it out there again.
#include "DynamicLookup.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
namespace cling {
namespace test {
  TestProxy* Tester = 0;

  extern "C" int printf(const char* fmt, ...);
  TestProxy::TestProxy(){}
  int TestProxy::Draw(){ return 12; }
  const char* TestProxy::getVersion(){ return "Interpreter.cpp"; }

  int TestProxy::Add10(int num) { return num + 10;}

  int TestProxy::Add(int a, int b) {
    return a + b;
  }

  void TestProxy::PrintString(std::string s) { printf("%s\n", s.c_str()); }

  bool TestProxy::PrintArray(int a[], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      printf("%i", a[i]);

    printf("%s", "\n");

    return true;
  }

  void TestProxy::PrintArray(float a[][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 5; ++j)
        printf("%i", (int)a[i][j]);

    printf("%s", "\n");
  }

  void TestProxy::PrintArray(int a[][4][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 4; ++j)
        for (unsigned k = 0; k < 5; ++k)
          printf("%i", a[i][j][k]);

    printf("%s", "\n");
  }

  SymbolResolverCallback::SymbolResolverCallback(Interpreter* interp)
    : InterpreterCallbacks(interp, /*enableExternalSemaSourceCallbacks*/true),
      m_TesterDecl(0) {
    m_Interpreter->process("cling::test::Tester = new cling::test::TestProxy();");
  }

  SymbolResolverCallback::~SymbolResolverCallback() { }

  bool SymbolResolverCallback::LookupObject(LookupResult& R, Scope* S) {
    if (m_IsRuntime) {
      // Only for demo resolve all unknown objects to cling::test::Tester
      if (!m_TesterDecl) {
        clang::Sema& SemaR = m_Interpreter->getSema();
        clang::NamespaceDecl* NSD = utils::Lookup::Namespace(&SemaR, "cling");
        NSD = utils::Lookup::Namespace(&SemaR, "test", NSD);
        m_TesterDecl = utils::Lookup::Named(&SemaR, "Tester", NSD);
      }
      assert (m_TesterDecl && "Tester not found!");
      R.addDecl(m_TesterDecl);
      return true; // Tell clang to continue.
    }

    if (ShouldResolveAtRuntime(R, S)) {
      ASTContext& C = R.getSema().getASTContext();
      DeclContext* DC = 0;
      // For DeclContext-less scopes like if (dyn_expr) {}
      while (!DC) {
        DC = static_cast<DeclContext*>(S->getEntity());
        S = S->getParent();
      }
      DeclarationName Name = R.getLookupName();
      IdentifierInfo* II = Name.getAsIdentifierInfo();
      SourceLocation Loc = R.getNameLoc();
      VarDecl* Res = VarDecl::Create(C, DC, Loc, Loc, II, C.DependentTy,
                                     /*TypeSourceInfo*/0, SC_None);

      // Annotate the decl to give a hint in cling. FIXME: Current implementation
      // is a gross hack, because TClingCallbacks shouldn't know about
      // EvaluateTSynthesizer at all!
      SourceRange invalidRange;
      Res->addAttr(new (C) AnnotateAttr(invalidRange, C, "__ResolveAtRuntime"));
      R.addDecl(Res);
      DC->addDecl(Res);
      // Say that we can handle the situation. Clang should try to recover
      return true;
    }

    return false;
  }

  bool SymbolResolverCallback::ShouldResolveAtRuntime(LookupResult& R,
                                                      Scope* S) {

    if (R.getLookupKind() != Sema::LookupOrdinaryName)
      return false;

    if (R.isForRedeclaration())
      return false;

    if (!R.empty())
      return false;

    // FIXME: Figure out better way to handle:
    // C++ [basic.lookup.classref]p1:
    //   In a class member access expression (5.2.5), if the . or -> token is
    //   immediately followed by an identifier followed by a <, the
    //   identifier must be looked up to determine whether the < is the
    //   beginning of a template argument list (14.2) or a less-than operator.
    //   The identifier is first looked up in the class of the object
    //   expression. If the identifier is not found, it is then looked up in
    //   the context of the entire postfix-expression and shall name a class
    //   or function template.
    //
    // We want to ignore object(.|->)member<template>
    if (R.getSema().PP.LookAhead(0).getKind() == tok::less)
      // TODO: check for . or -> in the cached token stream
      return false;

    for (Scope* DepScope = S; DepScope; DepScope = DepScope->getParent()) {
      if (DeclContext* Ctx = static_cast<DeclContext*>(DepScope->getEntity())) {
        if (!Ctx->isDependentContext())
          // For now we support only the prompt.
          if (isa<FunctionDecl>(Ctx))
            return true;
      }
    }

    return false;
  }

} // end test
} // end cling
<|endoftext|>


<commit_before>/*
 * MIT License
 *
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "Stamp.h"

namespace mediakit {

int64_t DeltaStamp::deltaStamp(int64_t stamp) {
    if(!_last_stamp){
        //第一次计算时间戳增量,时间戳增量为0
        _last_stamp = stamp;
        return 0;
    }

    int64_t ret = stamp - _last_stamp;
    if(ret >= 0){
        //时间戳增量为正，返回之
        _last_stamp = stamp;
        return ret;
    }

    //时间戳增量为负，说明时间戳回环了或回退了
    _last_stamp = stamp;
    return _playback ? ret : 0;
}

void DeltaStamp::setPlayBack(bool playback) {
    _playback = playback;
}

void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) {
    if(!pts){
        //没有播放时间戳,使其赋值为解码时间戳
        pts = dts;
    }

    //pts和dts的差值
    int pts_dts_diff = pts - dts;

    if(_last_dts != dts){
        //时间戳发生变更
        if(modifyStamp){
            _relativeStamp = _ticker.elapsedTime();
        }else{
            _relativeStamp += deltaStamp(dts);
        }
        _last_dts = dts;
    }
    dts_out = _relativeStamp;

    //////////////以下是播放时间戳的计算//////////////////
    if(pts_dts_diff > 200 || pts_dts_diff < -200){
        //如果差值大于200毫秒，则认为由于回环导致时间戳错乱了
        pts_dts_diff = 0;
    }

    pts_out = dts_out + pts_dts_diff;
    if(pts_out < 0){
        //时间戳不能小于0
        pts_out = 0;
    }
}

void Stamp::setRelativeStamp(int64_t relativeStamp) {
    _relativeStamp = relativeStamp;
}

int64_t Stamp::getRelativeStamp() const {
    return _relativeStamp;
}

}//namespace mediakit<commit_msg>修复时间戳跳跃可能导致的问题<commit_after>/*
 * MIT License
 *
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "Stamp.h"

#define MAX_DELTA_STAMP 300

namespace mediakit {

int64_t DeltaStamp::deltaStamp(int64_t stamp) {
    if(!_last_stamp){
        //第一次计算时间戳增量,时间戳增量为0
        _last_stamp = stamp;
        return 0;
    }

    int64_t ret = stamp - _last_stamp;
    if(ret >= 0){
        //时间戳增量为正，返回之
        _last_stamp = stamp;
        //在直播情况下，时间戳增量不得大于MAX_DELTA_STAMP
        return  ret < MAX_DELTA_STAMP ? ret : (_playback ? ret : 0);
    }

    //时间戳增量为负，说明时间戳回环了或回退了
    _last_stamp = stamp;
    return _playback ? ret : 0;
}

void DeltaStamp::setPlayBack(bool playback) {
    _playback = playback;
}

void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) {
    if(!pts){
        //没有播放时间戳,使其赋值为解码时间戳
        pts = dts;
    }

    //pts和dts的差值
    int pts_dts_diff = pts - dts;

    if(_last_dts != dts){
        //时间戳发生变更
        if(modifyStamp){
            _relativeStamp = _ticker.elapsedTime();
        }else{
            _relativeStamp += deltaStamp(dts);
        }
        _last_dts = dts;
    }
    dts_out = _relativeStamp;

    //////////////以下是播放时间戳的计算//////////////////
    if(pts_dts_diff > MAX_DELTA_STAMP || pts_dts_diff < -MAX_DELTA_STAMP){
        //如果差值太大，则认为由于回环导致时间戳错乱了
        pts_dts_diff = 0;
    }

    pts_out = dts_out + pts_dts_diff;
    if(pts_out < 0){
        //时间戳不能小于0
        pts_out = 0;
    }
}

void Stamp::setRelativeStamp(int64_t relativeStamp) {
    _relativeStamp = relativeStamp;
}

int64_t Stamp::getRelativeStamp() const {
    return _relativeStamp;
}

}//namespace mediakit<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * 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.
 */

/*
 * Usage:
 *   server {
 *     pagespeed    on|off;
 *   }
 */

extern "C" {
  #include <ngx_config.h>
  #include <ngx_core.h>
  #include <ngx_http.h>
}

#include "net/instaweb/public/version.h"

extern ngx_module_t ngx_pagespeed;

typedef struct {
  ngx_flag_t  active;
} ngx_http_pagespeed_loc_conf_t;

static ngx_command_t ngx_http_pagespeed_commands[] = {
  { ngx_string("pagespeed"),
    NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    ngx_conf_set_flag_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_pagespeed_loc_conf_t, active),
    NULL },

  ngx_null_command
};

static void*
ngx_http_pagespeed_create_loc_conf(ngx_conf_t* cf)
{
  ngx_http_pagespeed_loc_conf_t* conf;

  conf = static_cast<ngx_http_pagespeed_loc_conf_t*>(
      ngx_pcalloc(cf->pool, sizeof(ngx_http_pagespeed_loc_conf_t)));
  if (conf == NULL) {
    return NGX_CONF_ERROR;
  }
  conf->active = NGX_CONF_UNSET;
  return conf;
}

static char*
ngx_http_pagespeed_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child)
{
  ngx_http_pagespeed_loc_conf_t* prev =
      static_cast<ngx_http_pagespeed_loc_conf_t*>(parent);
  ngx_http_pagespeed_loc_conf_t* conf =
      static_cast<ngx_http_pagespeed_loc_conf_t*>(child);

  ngx_conf_merge_value(conf->active, prev->active, 0);  // Default off.

  return NGX_CONF_OK;
}

static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;

static
ngx_int_t ngx_http_pagespeed_header_filter(ngx_http_request_t* r)
{
  // We're adding content below, so switch to 'Transfer-Encoding: chunked' and
  // calculate on the fly.
  ngx_http_clear_content_length(r);
  return ngx_http_next_header_filter(r);
}

// Add a buffer to the end of the buffer chain indicating that we were processed
// through ngx_pagespeed.
static
ngx_int_t ngx_http_pagespeed_body_filter(ngx_http_request_t* r, ngx_chain_t* in)
{
  // Find the end of the buffer chain.
  ngx_chain_t* chain_link;
  int chain_contains_last_buffer = 0;
  for ( chain_link = in; chain_link != NULL; chain_link = chain_link->next ) {
    if (chain_link->buf->last_buf) {
      chain_contains_last_buffer = 1;
      if (chain_link->next != NULL) {
        ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0,
                      "Chain link thinks its last but has a child.");
        return NGX_ERROR;
      }
      break;  // Chain link now is the last link in the chain.
    }
  }

  if (!chain_contains_last_buffer) {
    // None of the buffers had last_buf set, meaning we have an incomplete chain
    // and are still waiting to get the final buffer.  Let other body filters
    // act on the buffers we have so far and wait until we're called again with
    // the last buffer.
    return ngx_http_next_body_filter(r, in);
  }

  // Prepare a new buffer to put the note into.
  ngx_buf_t* b = static_cast<ngx_buf_t*>(ngx_calloc_buf(r->pool));
  if (b == NULL) {
    return NGX_ERROR;
  }

  // Write to the new buffer.
  const char note[] = "<!-- Processed through ngx_pagespeed using PSOL version "
      MOD_PAGESPEED_VERSION_STRING " -->\n";
  int note_len = strlen(note);
  b->start = b->pos = static_cast<u_char*>(ngx_pnalloc(r->pool, note_len));
  strncpy((char*)b->pos, note, note_len);
  b->end = b->last = b->pos + note_len;
  b->temporary = 1;

  // Link the new buffer into the buffer chain.
  ngx_chain_t* added_link = static_cast<ngx_chain_t*>(
      ngx_alloc_chain_link(r->pool));
  if (added_link == NULL) {
    return NGX_ERROR;
  }

  added_link->buf = b;

  // Add our new link to the buffer chain.
  added_link->next = NULL;
  chain_link->next = added_link;

  // Mark our new link as the end of the chain.
  chain_link->buf->last_buf = 0;
  added_link->buf->last_buf = 1;
  chain_link->buf->last_in_chain = 0;
  added_link->buf->last_in_chain = 1;

  return ngx_http_next_body_filter(r, in);
}

static ngx_int_t
ngx_http_pagespeed_init(ngx_conf_t* cf)
{
  ngx_http_pagespeed_loc_conf_t* pagespeed_config;
  pagespeed_config = static_cast<ngx_http_pagespeed_loc_conf_t*>(
    ngx_http_conf_get_module_loc_conf(cf, ngx_pagespeed));

  if (pagespeed_config->active) {
    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_pagespeed_header_filter;

    ngx_http_next_body_filter = ngx_http_top_body_filter;
    ngx_http_top_body_filter = ngx_http_pagespeed_body_filter;
  }

  return NGX_OK;
}

static ngx_http_module_t ngx_http_pagespeed_module_ctx = {
  NULL,
  ngx_http_pagespeed_init,  // Post configuration.
  NULL,
  NULL,
  NULL,
  NULL,
  ngx_http_pagespeed_create_loc_conf,
  ngx_http_pagespeed_merge_loc_conf
};

ngx_module_t ngx_pagespeed = {
  NGX_MODULE_V1,
  &ngx_http_pagespeed_module_ctx,
  ngx_http_pagespeed_commands,
  NGX_HTTP_MODULE,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NGX_MODULE_V1_PADDING
};

<commit_msg>refactoring<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * 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.
 */

/*
 * Usage:
 *   server {
 *     pagespeed    on|off;
 *   }
 */

extern "C" {
  #include <ngx_config.h>
  #include <ngx_core.h>
  #include <ngx_http.h>
}

#include "net/instaweb/public/version.h"

extern ngx_module_t ngx_pagespeed;

typedef struct {
  ngx_flag_t  active;
} ngx_http_pagespeed_loc_conf_t;

static ngx_command_t ngx_http_pagespeed_commands[] = {
  { ngx_string("pagespeed"),
    NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    ngx_conf_set_flag_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_pagespeed_loc_conf_t, active),
    NULL },

  ngx_null_command
};

static void*
ngx_http_pagespeed_create_loc_conf(ngx_conf_t* cf)
{
  ngx_http_pagespeed_loc_conf_t* conf;

  conf = static_cast<ngx_http_pagespeed_loc_conf_t*>(
      ngx_pcalloc(cf->pool, sizeof(ngx_http_pagespeed_loc_conf_t)));
  if (conf == NULL) {
    return NGX_CONF_ERROR;
  }
  conf->active = NGX_CONF_UNSET;
  return conf;
}

static char*
ngx_http_pagespeed_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child)
{
  ngx_http_pagespeed_loc_conf_t* prev =
      static_cast<ngx_http_pagespeed_loc_conf_t*>(parent);
  ngx_http_pagespeed_loc_conf_t* conf =
      static_cast<ngx_http_pagespeed_loc_conf_t*>(child);

  ngx_conf_merge_value(conf->active, prev->active, 0);  // Default off.

  return NGX_CONF_OK;
}

static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;

static
ngx_int_t ngx_http_pagespeed_header_filter(ngx_http_request_t* r)
{
  // We're adding content below, so switch to 'Transfer-Encoding: chunked' and
  // calculate on the fly.
  ngx_http_clear_content_length(r);
  return ngx_http_next_header_filter(r);
}

// Add a buffer to the end of the buffer chain indicating that we were processed
// through ngx_pagespeed.
static
ngx_int_t ngx_http_pagespeed_note_processed(ngx_http_request_t* r,
                                            ngx_chain_t* in) {
  // Find the end of the buffer chain.
  ngx_chain_t* chain_link;
  int chain_contains_last_buffer = 0;
  for (chain_link = in; chain_link != NULL; chain_link = chain_link->next) {
    if (chain_link->buf->last_buf) {
      chain_contains_last_buffer = 1;
      if (chain_link->next != NULL) {
        ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0,
                      "Chain link thinks its last but has a child.");
        return NGX_ERROR;
      }
      break;  // Chain link now is the last link in the chain.
    }
  }

  if (!chain_contains_last_buffer) {
    // None of the buffers had last_buf set, meaning we have an incomplete chain
    // and are still waiting to get the final buffer.  Wait until we're called
    // again with the last buffer.
    return NGX_OK;
  }

  // Prepare a new buffer to put the note into.
  ngx_buf_t* b = static_cast<ngx_buf_t*>(ngx_calloc_buf(r->pool));
  if (b == NULL) {
    return NGX_ERROR;
  }

  // Write to the new buffer.
  const char note[] = "<!-- Processed through ngx_pagespeed using PSOL version "
      MOD_PAGESPEED_VERSION_STRING " -->\n";
  int note_len = strlen(note);
  b->start = b->pos = static_cast<u_char*>(ngx_pnalloc(r->pool, note_len));
  strncpy((char*)b->pos, note, note_len);
  b->end = b->last = b->pos + note_len;
  b->temporary = 1;

  // Link the new buffer into the buffer chain.
  ngx_chain_t* added_link = static_cast<ngx_chain_t*>(
      ngx_alloc_chain_link(r->pool));
  if (added_link == NULL) {
    return NGX_ERROR;
  }

  added_link->buf = b;

  // Add our new link to the buffer chain.
  added_link->next = NULL;
  chain_link->next = added_link;

  // Mark our new link as the end of the chain.
  chain_link->buf->last_buf = 0;
  added_link->buf->last_buf = 1;
  chain_link->buf->last_in_chain = 0;
  added_link->buf->last_in_chain = 1;

  return NGX_OK;
}

// Replace each buffer with a new one that's been through HtmlParse.
static
ngx_int_t ngx_http_pagespeed_parse_and_replace_buffer(ngx_http_request_t* r,
                                                      ngx_chain_t* in) {
  ngx_chain_t* chain_link;
  for (chain_link = in; chain_link != NULL; chain_link = chain_link->next) {
    // working here
  }
  return NGX_OK;
}

static
ngx_int_t ngx_http_pagespeed_body_filter(ngx_http_request_t* r, ngx_chain_t* in)
{
  ngx_int_t rc;

  rc = ngx_http_pagespeed_parse_and_replace_buffer(r, in);
  if (rc != NGX_OK) {
    return rc;
  }

  rc = ngx_http_pagespeed_note_processed(r, in);
  if (rc != NGX_OK) {
    return rc;
  }

  return ngx_http_next_body_filter(r, in);
}

static ngx_int_t
ngx_http_pagespeed_init(ngx_conf_t* cf)
{
  ngx_http_pagespeed_loc_conf_t* pagespeed_config;
  pagespeed_config = static_cast<ngx_http_pagespeed_loc_conf_t*>(
    ngx_http_conf_get_module_loc_conf(cf, ngx_pagespeed));

  if (pagespeed_config->active) {
    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_pagespeed_header_filter;

    ngx_http_next_body_filter = ngx_http_top_body_filter;
    ngx_http_top_body_filter = ngx_http_pagespeed_body_filter;
  }

  return NGX_OK;
}

static ngx_http_module_t ngx_http_pagespeed_module_ctx = {
  NULL,
  ngx_http_pagespeed_init,  // Post configuration.
  NULL,
  NULL,
  NULL,
  NULL,
  ngx_http_pagespeed_create_loc_conf,
  ngx_http_pagespeed_merge_loc_conf
};

ngx_module_t ngx_pagespeed = {
  NGX_MODULE_V1,
  &ngx_http_pagespeed_module_ctx,
  ngx_http_pagespeed_commands,
  NGX_HTTP_MODULE,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NGX_MODULE_V1_PADDING
};

<|endoftext|>


<commit_before>#include "include/XyLatinStr.hpp"
#include "include/XyUTF8Str.hpp"
#include "include/XID_map.hpp"
#include "include/XID_DOMDocument.hpp"

#include "DOMPrint.hpp"
#include "CommonSubSequenceAlgorithms.hpp"
#include "Tools.hpp"
#include "Diff_NodesManager.hpp"
#include "Diff_DeltaConstructor.hpp"
#include "Diff_UniqueIdHandler.hpp"
#include "DeltaException.hpp"
#include "DeltaManager.hpp"

#include "xercesc/dom/DOMNamedNodeMap.hpp"
#include "xercesc/dom/DOMElement.hpp"
#include "xercesc/validators/DTD/DTDValidator.hpp"

#include "infra/general/Log.hpp"

#include <stdio.h>
#include <map>
#include <queue>
#include <list>
#include <math.h>
#include <fstream>
#include "infra/general/hash_map.hpp"

#include <sys/timeb.h>
#include <time.h>

//class DTDValidator;

/*******************************************************************
 *                                                                 *
 *                                                                 *
 * Time Profiling Functions                                        *
 *                                                                 *
 * Author: Gregory COBENA                                          *
 *                                                                 *
 *                                                                 *
 *                                                                 *
 *******************************************************************/

unsigned long long int clocksComputeDelta           ;

unsigned long long int clocksReadDocuments          ;
unsigned long long int clocksRegisterSubtree        ;
unsigned long long int clocksTopDownMatch           ;
unsigned long long int clocksOptimize               ;
unsigned long long int clocksConstructDeltaDocument ;
unsigned long long int clocksSaveDelta              ;

/* 1 to 10 ms resolution functions */

// We can use: getitimer, setitimer

#ifdef WIN32
#ifndef ftime
	#define timeb	__timeb32
	#define ftime	_ftime32_s
#endif
#endif
struct timeb timeStart ;
struct timeb timeLast ;

XERCES_CPP_NAMESPACE_USE

void TimeInit(void) {
  vddprintf(("TimeInit\n")) ;
	ftime ( &timeStart );
	timeLast = timeStart ;
	}

void TimeStep(void) {
  struct timeb timeEnd ;
	ftime( &timeEnd );
	int secLast = (int) (timeEnd.time-timeLast.time) ;
	long mLast = timeEnd.millitm - timeLast.millitm ;
	mLast += 1000* secLast ;
	int secStart = (int) (timeEnd.time-timeStart.time) ;
	long mStart = timeEnd.millitm - timeStart.millitm ;
	mStart += 1000* secStart ;

	vddprintf(("<!> time since previous step=%ldms, since timer init=%ldms\n", mLast, mStart));
	timeLast = timeEnd ;
	}

/*******************************************************************
 *                                                                 *
 *                                                                 *
 * Main Functions                                                  *
 *                                                                 *
 * Author: Gregory COBENA                                          *
 *                                                                 *
 *                                                                 *
 *                                                                 *
 *******************************************************************/

// apelat din XyDiff() de mai jos
XID_DOMDocument* XidXyDiff(XID_DOMDocument* v0XML, const char *doc1name, XID_DOMDocument* v1XML, const char *doc2name, bool ignoreSpacesFlag=false, bool verbose=false) {
#ifdef HW_PROF
	clocksRegisterSubtree        = 0 ;
	clocksTopDownMatch           = 0 ;
		clocksGetBestCandidate     = 0 ;
		clocksQueueOps             = 0 ;
		clocksPropagateAssign      = 0 ;
	clocksOptimize               = 0 ;
	clocksConstructDeltaDocument = 0 ;
		clocksCDDinitDomDelta      = 0 ;
		clocksCDDprepareVectors    = 0 ;
		clocksCDDsaveXidMap        = 0 ;
		clocksCDDcomputeWeakMove   = 0 ;
		clocksCDDdetectUpdate      = 0 ;
		clocksCDDaddAttributeOps   = 0 ;
		clocksConstructDOMDelta    = 0 ;
#endif

	/* ---- [[ Phase 1: ]] Compute signatures and weight for subtrees on both documents ---- */

	TRACE("PHASE 1: Register ID-Attributes");

	UniqueIdHandler myUniqueIdHandler ;

	// Create object that manages meta-data for nodes of both documents
	class NodesManager xyMappingEngine;

	vddprintf(("\n+++ Phase 1: Compute signature and weight for subtrees on both documents +++\n\n")) ;

	xyMappingEngine.setUniqueIdHandler( &myUniqueIdHandler );
	TRACE("PHASE 1: Register version 1");
	xyMappingEngine.registerSourceDocument( v0XML );
	TRACE("PHASE 1: Register version 2");
	xyMappingEngine.registerResultDocument( v1XML );

	int v0rootID = xyMappingEngine.sourceNumberOfNodes ;
	int v1rootID = xyMappingEngine.resultNumberOfNodes ;

	/* ---- [[ Phase 2: ]] Apply Bottom-Up Lazy-Down Algorithm ---- */

	vddprintf(("\n+++ Phase 2: Apply BULD (Bottom-Up Lazy Down) matching algorithm starting from heaviest subtrees +++\n\n")) ;

	TRACE("PHASE 2: Match by ID-Attributes");
	vddprintf(("Match node which have ID attributes\n")) ;
	xyMappingEngine.MatchById( v1rootID );

	TRACE("PHASE 2: Full Bottom-up propagation pass #1");
	vddprintf(("Full Bottom-up propagation pass #1\n")) ;
	xyMappingEngine.FullBottomUp( v1rootID );

	TRACE("PHASE 2: Apply BULD Algorithm");
	vddprintf(("Top-down matching on new document\n")) ;
	xyMappingEngine.topdownMatch( v0rootID, v1rootID );

	vddprintf(("\nAlgorithm Finished OK\n\n")) ;

	if (verbose) xyMappingEngine.PrintStats();

	/* ---- [[ Phase 3: ]] Peephole Optimization to Propagate Matchings ---- */

	// Due to complete re-writting, this phase has been disabled for the moment

	vddprintf(("\n+++ Phase 3: Peephole optimization to propagate matchings +++\n\n")) ;
	vddprintf(("\nskipping\n")) ;

	TRACE("PHASE 3: Optimize matchings");
	xyMappingEngine.Optimize( v0rootID );

	/* ---- [[ Phase 4: ]] Construct the Delta ---- */

	vddprintf(("\n+++ Phase 4: Construct the Delta +++\n\n")) ;

	TRACE("PHASE 4: Construct result delta");

	class DeltaConstructor myDeltaConstructor(&xyMappingEngine, doc1name, v0XML, doc2name, v1XML, ignoreSpacesFlag) ;
	myDeltaConstructor.constructDeltaDocument() ;

	TRACE("PHASE 4: Return result delta");

	return myDeltaConstructor.getDeltaDocument();
}

<commit_msg>Changed _ftime32_s and __timeb32 to their arch independent equivalents<commit_after>#include "include/XyLatinStr.hpp"
#include "include/XyUTF8Str.hpp"
#include "include/XID_map.hpp"
#include "include/XID_DOMDocument.hpp"

#include "DOMPrint.hpp"
#include "CommonSubSequenceAlgorithms.hpp"
#include "Tools.hpp"
#include "Diff_NodesManager.hpp"
#include "Diff_DeltaConstructor.hpp"
#include "Diff_UniqueIdHandler.hpp"
#include "DeltaException.hpp"
#include "DeltaManager.hpp"

#include "xercesc/dom/DOMNamedNodeMap.hpp"
#include "xercesc/dom/DOMElement.hpp"
#include "xercesc/validators/DTD/DTDValidator.hpp"

#include "infra/general/Log.hpp"

#include <stdio.h>
#include <map>
#include <queue>
#include <list>
#include <math.h>
#include <fstream>
#include "infra/general/hash_map.hpp"

#include <sys/timeb.h>
#include <time.h>

//class DTDValidator;

/*******************************************************************
 *                                                                 *
 *                                                                 *
 * Time Profiling Functions                                        *
 *                                                                 *
 * Author: Gregory COBENA                                          *
 *                                                                 *
 *                                                                 *
 *                                                                 *
 *******************************************************************/

unsigned long long int clocksComputeDelta           ;

unsigned long long int clocksReadDocuments          ;
unsigned long long int clocksRegisterSubtree        ;
unsigned long long int clocksTopDownMatch           ;
unsigned long long int clocksOptimize               ;
unsigned long long int clocksConstructDeltaDocument ;
unsigned long long int clocksSaveDelta              ;

/* 1 to 10 ms resolution functions */

// We can use: getitimer, setitimer

#ifdef WIN32
#ifndef ftime
	#define timeb	_timeb
	#define ftime	_ftime
#endif
#endif
struct timeb timeStart ;
struct timeb timeLast ;

XERCES_CPP_NAMESPACE_USE

void TimeInit(void) {
  vddprintf(("TimeInit\n")) ;
	ftime ( &timeStart );
	timeLast = timeStart ;
	}

void TimeStep(void) {
  struct timeb timeEnd ;
	ftime( &timeEnd );
	int secLast = (int) (timeEnd.time-timeLast.time) ;
	long mLast = timeEnd.millitm - timeLast.millitm ;
	mLast += 1000* secLast ;
	int secStart = (int) (timeEnd.time-timeStart.time) ;
	long mStart = timeEnd.millitm - timeStart.millitm ;
	mStart += 1000* secStart ;

	vddprintf(("<!> time since previous step=%ldms, since timer init=%ldms\n", mLast, mStart));
	timeLast = timeEnd ;
	}

/*******************************************************************
 *                                                                 *
 *                                                                 *
 * Main Functions                                                  *
 *                                                                 *
 * Author: Gregory COBENA                                          *
 *                                                                 *
 *                                                                 *
 *                                                                 *
 *******************************************************************/

// apelat din XyDiff() de mai jos
XID_DOMDocument* XidXyDiff(XID_DOMDocument* v0XML, const char *doc1name, XID_DOMDocument* v1XML, const char *doc2name, bool ignoreSpacesFlag=false, bool verbose=false) {
#ifdef HW_PROF
	clocksRegisterSubtree        = 0 ;
	clocksTopDownMatch           = 0 ;
		clocksGetBestCandidate     = 0 ;
		clocksQueueOps             = 0 ;
		clocksPropagateAssign      = 0 ;
	clocksOptimize               = 0 ;
	clocksConstructDeltaDocument = 0 ;
		clocksCDDinitDomDelta      = 0 ;
		clocksCDDprepareVectors    = 0 ;
		clocksCDDsaveXidMap        = 0 ;
		clocksCDDcomputeWeakMove   = 0 ;
		clocksCDDdetectUpdate      = 0 ;
		clocksCDDaddAttributeOps   = 0 ;
		clocksConstructDOMDelta    = 0 ;
#endif

	/* ---- [[ Phase 1: ]] Compute signatures and weight for subtrees on both documents ---- */

	TRACE("PHASE 1: Register ID-Attributes");

	UniqueIdHandler myUniqueIdHandler ;

	// Create object that manages meta-data for nodes of both documents
	class NodesManager xyMappingEngine;

	vddprintf(("\n+++ Phase 1: Compute signature and weight for subtrees on both documents +++\n\n")) ;

	xyMappingEngine.setUniqueIdHandler( &myUniqueIdHandler );
	TRACE("PHASE 1: Register version 1");
	xyMappingEngine.registerSourceDocument( v0XML );
	TRACE("PHASE 1: Register version 2");
	xyMappingEngine.registerResultDocument( v1XML );

	int v0rootID = xyMappingEngine.sourceNumberOfNodes ;
	int v1rootID = xyMappingEngine.resultNumberOfNodes ;

	/* ---- [[ Phase 2: ]] Apply Bottom-Up Lazy-Down Algorithm ---- */

	vddprintf(("\n+++ Phase 2: Apply BULD (Bottom-Up Lazy Down) matching algorithm starting from heaviest subtrees +++\n\n")) ;

	TRACE("PHASE 2: Match by ID-Attributes");
	vddprintf(("Match node which have ID attributes\n")) ;
	xyMappingEngine.MatchById( v1rootID );

	TRACE("PHASE 2: Full Bottom-up propagation pass #1");
	vddprintf(("Full Bottom-up propagation pass #1\n")) ;
	xyMappingEngine.FullBottomUp( v1rootID );

	TRACE("PHASE 2: Apply BULD Algorithm");
	vddprintf(("Top-down matching on new document\n")) ;
	xyMappingEngine.topdownMatch( v0rootID, v1rootID );

	vddprintf(("\nAlgorithm Finished OK\n\n")) ;

	if (verbose) xyMappingEngine.PrintStats();

	/* ---- [[ Phase 3: ]] Peephole Optimization to Propagate Matchings ---- */

	// Due to complete re-writting, this phase has been disabled for the moment

	vddprintf(("\n+++ Phase 3: Peephole optimization to propagate matchings +++\n\n")) ;
	vddprintf(("\nskipping\n")) ;

	TRACE("PHASE 3: Optimize matchings");
	xyMappingEngine.Optimize( v0rootID );

	/* ---- [[ Phase 4: ]] Construct the Delta ---- */

	vddprintf(("\n+++ Phase 4: Construct the Delta +++\n\n")) ;

	TRACE("PHASE 4: Construct result delta");

	class DeltaConstructor myDeltaConstructor(&xyMappingEngine, doc1name, v0XML, doc2name, v1XML, ignoreSpacesFlag) ;
	myDeltaConstructor.constructDeltaDocument() ;

	TRACE("PHASE 4: Return result delta");

	return myDeltaConstructor.getDeltaDocument();
}

<|endoftext|>


<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <franka/rate_limiting.h>

#include <Eigen/Dense>

#include <franka/control_tools.h>

namespace franka {

namespace {

Eigen::Vector3d limitRate(double max_velocity,
                          double max_acceleration,
                          double max_jerk,
                          const Eigen::Vector3d& commanded_velocity,
                          const Eigen::Vector3d& last_commanded_velocity,
                          const Eigen::Vector3d& last_commanded_acceleration) {
  // Differentiate to get jerk
  Eigen::Vector3d commanded_jerk =
      (((commanded_velocity - last_commanded_velocity) / kDeltaT) - last_commanded_acceleration) /
      kDeltaT;

  // Limit jerk and integrate to get desired acceleration
  Eigen::Vector3d commanded_acceleration = last_commanded_acceleration;
  if (commanded_jerk.norm() > kNormEps) {
    commanded_acceleration += (commanded_jerk / commanded_jerk.norm()) *
                              std::max(std::min(commanded_jerk.norm(), max_jerk), -max_jerk) *
                              kDeltaT;
  }

  // Compute Euclidean distance to the max velocity vector that would be reached starting from
  // last_commanded_velocity with the direction of the desired acceleration
  Eigen::Vector3d unit_commanded_acceleration =
      commanded_acceleration / commanded_acceleration.norm();
  double dot_product = unit_commanded_acceleration.transpose() * last_commanded_velocity;
  double distance_to_max_velocity =
      -dot_product + std::sqrt(pow(dot_product, 2.0) - last_commanded_velocity.squaredNorm() +
                               pow(max_velocity, 2.0));

  // Compute safe acceleration limits
  double safe_max_acceleration =
      std::min((max_jerk / max_acceleration) * distance_to_max_velocity, max_acceleration);

  // Limit acceleration and integrate to get desired velocities
  Eigen::Vector3d limited_commanded_velocity = last_commanded_velocity;

  if (commanded_acceleration.norm() > kNormEps) {
    limited_commanded_velocity += unit_commanded_acceleration *
                                  std::min(commanded_acceleration.norm(), safe_max_acceleration) *
                                  kDeltaT;
  }

  return limited_commanded_velocity;
}

}  // anonymous namespace

std::array<double, 7> limitRate(const std::array<double, 7>& max_derivatives,
                                const std::array<double, 7>& commanded_values,
                                const std::array<double, 7>& last_commanded_values) {
  if (!std::all_of(commanded_values.begin(), commanded_values.end(),
                   [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("Commanding value is infinite or NaN.");
  }
  std::array<double, 7> limited_values{};
  for (size_t i = 0; i < 7; i++) {
    double commanded_derivative = (commanded_values[i] - last_commanded_values[i]) / kDeltaT;
    limited_values[i] =
        last_commanded_values[i] +
        std::max(std::min(commanded_derivative, max_derivatives[i]), -max_derivatives[i]) * kDeltaT;
  }
  return limited_values;
}

double limitRate(double max_velocity,
                 double max_acceleration,
                 double max_jerk,
                 double commanded_velocity,
                 double last_commanded_velocity,
                 double last_commanded_acceleration) {
  if (!std::isfinite(commanded_velocity)) {
    throw std::invalid_argument("commanded_velocity is infinite or NaN.");
  }
  // Differentiate to get jerk
  double commanded_jerk =
      (((commanded_velocity - last_commanded_velocity) / kDeltaT) - last_commanded_acceleration) /
      kDeltaT;

  // Limit jerk and integrate to get acceleration
  double commanded_acceleration = last_commanded_acceleration +
                                  std::max(std::min(commanded_jerk, max_jerk), -max_jerk) * kDeltaT;

  // Compute acceleration limits
  double safe_max_acceleration = std::min(
      (max_jerk / max_acceleration) * (max_velocity - last_commanded_velocity), max_acceleration);
  double safe_min_acceleration = std::max(
      (max_jerk / max_acceleration) * (-max_velocity - last_commanded_velocity), -max_acceleration);

  // Limit acceleration and integrate to get desired velocities
  return last_commanded_velocity +
         std::max(std::min(commanded_acceleration, safe_max_acceleration), safe_min_acceleration) *
             kDeltaT;
}

double limitRate(double max_velocity,
                 double max_acceleration,
                 double max_jerk,
                 double commanded_position,
                 double last_commanded_position,
                 double last_commanded_velocity,
                 double last_commanded_acceleration) {
  if (!std::isfinite(commanded_position)) {
    throw std::invalid_argument("commanded_position is infinite or NaN.");
  }
  return last_commanded_position +
         limitRate(max_velocity, max_acceleration, max_jerk,
                   (commanded_position - last_commanded_position) / kDeltaT,
                   last_commanded_velocity, last_commanded_acceleration) *
             kDeltaT;
}

std::array<double, 7> limitRate(const std::array<double, 7>& max_velocity,
                                const std::array<double, 7>& max_acceleration,
                                const std::array<double, 7>& max_jerk,
                                const std::array<double, 7>& commanded_velocities,
                                const std::array<double, 7>& last_commanded_velocities,
                                const std::array<double, 7>& last_commanded_accelerations) {
  if (!std::all_of(commanded_velocities.begin(), commanded_velocities.end(),
                   [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("commanded_velocities is infinite or NaN.");
  }
  std::array<double, 7> limited_commanded_velocities{};

  for (size_t i = 0; i < 7; i++) {
    limited_commanded_velocities[i] =
        limitRate(max_velocity[i], max_acceleration[i], max_jerk[i], commanded_velocities[i],
                  last_commanded_velocities[i], last_commanded_accelerations[i]);
  }
  return limited_commanded_velocities;
}

std::array<double, 7> limitRate(const std::array<double, 7>& max_velocity,
                                const std::array<double, 7>& max_acceleration,
                                const std::array<double, 7>& max_jerk,
                                const std::array<double, 7>& commanded_positions,
                                const std::array<double, 7>& last_commanded_positions,
                                const std::array<double, 7>& last_commanded_velocities,
                                const std::array<double, 7>& last_commanded_accelerations) {
  if (!std::all_of(commanded_positions.begin(), commanded_positions.end(),
                   [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("commanded_positions is infinite or NaN.");
  }
  std::array<double, 7> limited_commanded_positions{};
  for (size_t i = 0; i < 7; i++) {
    limited_commanded_positions[i] = limitRate(
        max_velocity[i], max_acceleration[i], max_jerk[i], commanded_positions[i],
        last_commanded_positions[i], last_commanded_velocities[i], last_commanded_accelerations[i]);
  }
  return limited_commanded_positions;
}

std::array<double, 6> limitRate(
    double max_translational_velocity,
    double max_translational_acceleration,
    double max_translational_jerk,
    double max_rotational_velocity,
    double max_rotational_acceleration,
    double max_rotational_jerk,
    const std::array<double, 6>& O_dP_EE_c,          // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_dP_EE_c,     // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_ddP_EE_c) {  // NOLINT(readability-identifier-naming)
  if (!std::all_of(O_dP_EE_c.begin(), O_dP_EE_c.end(), [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("O_dP_EE_c is infinite or NaN.");
  }
  Eigen::Matrix<double, 6, 1> dx(O_dP_EE_c.data());
  Eigen::Matrix<double, 6, 1> last_dx(last_O_dP_EE_c.data());
  Eigen::Matrix<double, 6, 1> last_ddx(last_O_ddP_EE_c.data());

  dx.head(3) << limitRate(max_translational_velocity, max_translational_acceleration,
                          max_translational_jerk, dx.head(3), last_dx.head(3), last_ddx.head(3));
  dx.tail(3) << limitRate(max_rotational_velocity, max_rotational_acceleration, max_rotational_jerk,
                          dx.tail(3), last_dx.tail(3), last_ddx.tail(3));

  std::array<double, 6> limited_values{};
  Eigen::Map<Eigen::Matrix<double, 6, 1>>(&limited_values[0], 6, 1) = dx;
  return limited_values;
}

std::array<double, 16> limitRate(
    double max_translational_velocity,
    double max_translational_acceleration,
    double max_translational_jerk,
    double max_rotational_velocity,
    double max_rotational_acceleration,
    double max_rotational_jerk,
    const std::array<double, 16>& O_T_EE_c,          // NOLINT(readability-identifier-naming)
    const std::array<double, 16>& last_O_T_EE_c,     // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_dP_EE_c,     // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_ddP_EE_c) {  // NOLINT(readability-identifier-naming)
  if (!std::all_of(O_T_EE_c.begin(), O_T_EE_c.end(), [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("O_T_EE_c is infinite or NaN.");
  }
  if (!isHomogeneousTransformation(O_T_EE_c)) {
    throw std::invalid_argument(
        "O_T_EE_c is invalid transformation matrix. Has to be column "
        "major!");
  }
  Eigen::Matrix<double, 6, 1> dx;
  Eigen::Affine3d commanded_pose(Eigen::Matrix4d::Map(O_T_EE_c.data()));
  Eigen::Affine3d limited_commanded_pose = Eigen::Affine3d::Identity();
  Eigen::Affine3d last_commanded_pose(Eigen::Matrix4d::Map(last_O_T_EE_c.data()));

  // Compute translational velocity
  dx.head(3) << (commanded_pose.translation() - last_commanded_pose.translation()) / kDeltaT;

  // Compute rotational velocity
  Eigen::AngleAxisd rot_difference(commanded_pose.linear() *
                                   last_commanded_pose.linear().transpose());
  dx.tail(3) << rot_difference.axis() * rot_difference.angle() / kDeltaT;

  // Limit the rate of the twist
  std::array<double, 6> commanded_O_dP_EE_c{};  // NOLINT(readability-identifier-naming)
  Eigen::Map<Eigen::Matrix<double, 6, 1>>(&commanded_O_dP_EE_c[0], 6, 1) = dx;
  commanded_O_dP_EE_c =
      limitRate(max_translational_velocity, max_translational_acceleration, max_translational_jerk,
                kFactorCartesianRotationPoseInterface * max_rotational_velocity,
                kFactorCartesianRotationPoseInterface * max_rotational_acceleration,
                kFactorCartesianRotationPoseInterface * max_rotational_jerk, commanded_O_dP_EE_c,
                last_O_dP_EE_c, last_O_ddP_EE_c);
  dx = Eigen::Matrix<double, 6, 1>(commanded_O_dP_EE_c.data());

  // Integrate limited twist
  limited_commanded_pose.translation() << last_commanded_pose.translation() + dx.head(3) * kDeltaT;
  limited_commanded_pose.linear() << last_commanded_pose.linear();
  if (dx.tail(3).norm() > kNormEps) {
    Eigen::Matrix3d omega_skew;
    Eigen::Vector3d w_norm(dx.tail(3) / dx.tail(3).norm());
    double theta = kDeltaT * dx.tail(3).norm();
    omega_skew << 0, -w_norm(2), w_norm(1), w_norm(2), 0, -w_norm(0), -w_norm(1), w_norm(0), 0;
    // NOLINTNEXTLINE(readability-identifier-naming)
    Eigen::Matrix3d R = Eigen::Matrix3d::Identity() + sin(theta) * omega_skew +
                        (1.0 - cos(theta)) * (omega_skew * omega_skew);
    limited_commanded_pose.linear() << R * last_commanded_pose.linear();
  }

  std::array<double, 16> limited_values{};
  Eigen::Map<Eigen::Matrix4d>(&limited_values[0], 4, 4) = limited_commanded_pose.matrix();
  return limited_values;
}

}  // namespace franka
<commit_msg>Fix formatting<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <franka/rate_limiting.h>

#include <Eigen/Dense>

#include <franka/control_tools.h>

namespace franka {

namespace {

Eigen::Vector3d limitRate(double max_velocity,
                          double max_acceleration,
                          double max_jerk,
                          const Eigen::Vector3d& commanded_velocity,
                          const Eigen::Vector3d& last_commanded_velocity,
                          const Eigen::Vector3d& last_commanded_acceleration) {
  // Differentiate to get jerk
  Eigen::Vector3d commanded_jerk =
      (((commanded_velocity - last_commanded_velocity) / kDeltaT) - last_commanded_acceleration) /
      kDeltaT;

  // Limit jerk and integrate to get desired acceleration
  Eigen::Vector3d commanded_acceleration = last_commanded_acceleration;
  if (commanded_jerk.norm() > kNormEps) {
    commanded_acceleration += (commanded_jerk / commanded_jerk.norm()) *
                              std::max(std::min(commanded_jerk.norm(), max_jerk), -max_jerk) *
                              kDeltaT;
  }

  // Compute Euclidean distance to the max velocity vector that would be reached starting from
  // last_commanded_velocity with the direction of the desired acceleration
  Eigen::Vector3d unit_commanded_acceleration =
      commanded_acceleration / commanded_acceleration.norm();
  double dot_product = unit_commanded_acceleration.transpose() * last_commanded_velocity;
  double distance_to_max_velocity =
      -dot_product + std::sqrt(pow(dot_product, 2.0) - last_commanded_velocity.squaredNorm() +
                               pow(max_velocity, 2.0));

  // Compute safe acceleration limits
  double safe_max_acceleration =
      std::min((max_jerk / max_acceleration) * distance_to_max_velocity, max_acceleration);

  // Limit acceleration and integrate to get desired velocities
  Eigen::Vector3d limited_commanded_velocity = last_commanded_velocity;

  if (commanded_acceleration.norm() > kNormEps) {
    limited_commanded_velocity += unit_commanded_acceleration *
                                  std::min(commanded_acceleration.norm(), safe_max_acceleration) *
                                  kDeltaT;
  }

  return limited_commanded_velocity;
}

}  // anonymous namespace

std::array<double, 7> limitRate(const std::array<double, 7>& max_derivatives,
                                const std::array<double, 7>& commanded_values,
                                const std::array<double, 7>& last_commanded_values) {
  if (!std::all_of(commanded_values.begin(), commanded_values.end(),
                   [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("Commanding value is infinite or NaN.");
  }
  std::array<double, 7> limited_values{};
  for (size_t i = 0; i < 7; i++) {
    double commanded_derivative = (commanded_values[i] - last_commanded_values[i]) / kDeltaT;
    limited_values[i] =
        last_commanded_values[i] +
        std::max(std::min(commanded_derivative, max_derivatives[i]), -max_derivatives[i]) * kDeltaT;
  }
  return limited_values;
}

double limitRate(double max_velocity,
                 double max_acceleration,
                 double max_jerk,
                 double commanded_velocity,
                 double last_commanded_velocity,
                 double last_commanded_acceleration) {
  if (!std::isfinite(commanded_velocity)) {
    throw std::invalid_argument("commanded_velocity is infinite or NaN.");
  }
  // Differentiate to get jerk
  double commanded_jerk =
      (((commanded_velocity - last_commanded_velocity) / kDeltaT) - last_commanded_acceleration) /
      kDeltaT;

  // Limit jerk and integrate to get acceleration
  double commanded_acceleration = last_commanded_acceleration +
                                  std::max(std::min(commanded_jerk, max_jerk), -max_jerk) * kDeltaT;

  // Compute acceleration limits
  double safe_max_acceleration = std::min(
      (max_jerk / max_acceleration) * (max_velocity - last_commanded_velocity), max_acceleration);
  double safe_min_acceleration = std::max(
      (max_jerk / max_acceleration) * (-max_velocity - last_commanded_velocity), -max_acceleration);

  // Limit acceleration and integrate to get desired velocities
  return last_commanded_velocity +
         std::max(std::min(commanded_acceleration, safe_max_acceleration), safe_min_acceleration) *
             kDeltaT;
}

double limitRate(double max_velocity,
                 double max_acceleration,
                 double max_jerk,
                 double commanded_position,
                 double last_commanded_position,
                 double last_commanded_velocity,
                 double last_commanded_acceleration) {
  if (!std::isfinite(commanded_position)) {
    throw std::invalid_argument("commanded_position is infinite or NaN.");
  }
  return last_commanded_position +
         limitRate(max_velocity, max_acceleration, max_jerk,
                   (commanded_position - last_commanded_position) / kDeltaT,
                   last_commanded_velocity, last_commanded_acceleration) *
             kDeltaT;
}

std::array<double, 7> limitRate(const std::array<double, 7>& max_velocity,
                                const std::array<double, 7>& max_acceleration,
                                const std::array<double, 7>& max_jerk,
                                const std::array<double, 7>& commanded_velocities,
                                const std::array<double, 7>& last_commanded_velocities,
                                const std::array<double, 7>& last_commanded_accelerations) {
  if (!std::all_of(commanded_velocities.begin(), commanded_velocities.end(),
                   [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("commanded_velocities is infinite or NaN.");
  }
  std::array<double, 7> limited_commanded_velocities{};

  for (size_t i = 0; i < 7; i++) {
    limited_commanded_velocities[i] =
        limitRate(max_velocity[i], max_acceleration[i], max_jerk[i], commanded_velocities[i],
                  last_commanded_velocities[i], last_commanded_accelerations[i]);
  }
  return limited_commanded_velocities;
}

std::array<double, 7> limitRate(const std::array<double, 7>& max_velocity,
                                const std::array<double, 7>& max_acceleration,
                                const std::array<double, 7>& max_jerk,
                                const std::array<double, 7>& commanded_positions,
                                const std::array<double, 7>& last_commanded_positions,
                                const std::array<double, 7>& last_commanded_velocities,
                                const std::array<double, 7>& last_commanded_accelerations) {
  if (!std::all_of(commanded_positions.begin(), commanded_positions.end(),
                   [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("commanded_positions is infinite or NaN.");
  }
  std::array<double, 7> limited_commanded_positions{};
  for (size_t i = 0; i < 7; i++) {
    limited_commanded_positions[i] = limitRate(
        max_velocity[i], max_acceleration[i], max_jerk[i], commanded_positions[i],
        last_commanded_positions[i], last_commanded_velocities[i], last_commanded_accelerations[i]);
  }
  return limited_commanded_positions;
}

std::array<double, 6> limitRate(
    double max_translational_velocity,
    double max_translational_acceleration,
    double max_translational_jerk,
    double max_rotational_velocity,
    double max_rotational_acceleration,
    double max_rotational_jerk,
    const std::array<double, 6>& O_dP_EE_c,          // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_dP_EE_c,     // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_ddP_EE_c) {  // NOLINT(readability-identifier-naming)
  if (!std::all_of(O_dP_EE_c.begin(), O_dP_EE_c.end(), [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("O_dP_EE_c is infinite or NaN.");
  }
  Eigen::Matrix<double, 6, 1> dx(O_dP_EE_c.data());
  Eigen::Matrix<double, 6, 1> last_dx(last_O_dP_EE_c.data());
  Eigen::Matrix<double, 6, 1> last_ddx(last_O_ddP_EE_c.data());

  dx.head(3) << limitRate(max_translational_velocity, max_translational_acceleration,
                          max_translational_jerk, dx.head(3), last_dx.head(3), last_ddx.head(3));
  dx.tail(3) << limitRate(max_rotational_velocity, max_rotational_acceleration, max_rotational_jerk,
                          dx.tail(3), last_dx.tail(3), last_ddx.tail(3));

  std::array<double, 6> limited_values{};
  Eigen::Map<Eigen::Matrix<double, 6, 1>>(&limited_values[0], 6, 1) = dx;
  return limited_values;
}

std::array<double, 16> limitRate(
    double max_translational_velocity,
    double max_translational_acceleration,
    double max_translational_jerk,
    double max_rotational_velocity,
    double max_rotational_acceleration,
    double max_rotational_jerk,
    const std::array<double, 16>& O_T_EE_c,          // NOLINT(readability-identifier-naming)
    const std::array<double, 16>& last_O_T_EE_c,     // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_dP_EE_c,     // NOLINT(readability-identifier-naming)
    const std::array<double, 6>& last_O_ddP_EE_c) {  // NOLINT(readability-identifier-naming)
  if (!std::all_of(O_T_EE_c.begin(), O_T_EE_c.end(), [](double d) { return std::isfinite(d); })) {
    throw std::invalid_argument("O_T_EE_c is infinite or NaN.");
  }
  if (!isHomogeneousTransformation(O_T_EE_c)) {
    throw std::invalid_argument(
        "O_T_EE_c is invalid transformation matrix. Has to be column major!");
  }
  Eigen::Matrix<double, 6, 1> dx;
  Eigen::Affine3d commanded_pose(Eigen::Matrix4d::Map(O_T_EE_c.data()));
  Eigen::Affine3d limited_commanded_pose = Eigen::Affine3d::Identity();
  Eigen::Affine3d last_commanded_pose(Eigen::Matrix4d::Map(last_O_T_EE_c.data()));

  // Compute translational velocity
  dx.head(3) << (commanded_pose.translation() - last_commanded_pose.translation()) / kDeltaT;

  // Compute rotational velocity
  Eigen::AngleAxisd rot_difference(commanded_pose.linear() *
                                   last_commanded_pose.linear().transpose());
  dx.tail(3) << rot_difference.axis() * rot_difference.angle() / kDeltaT;

  // Limit the rate of the twist
  std::array<double, 6> commanded_O_dP_EE_c{};  // NOLINT(readability-identifier-naming)
  Eigen::Map<Eigen::Matrix<double, 6, 1>>(&commanded_O_dP_EE_c[0], 6, 1) = dx;
  commanded_O_dP_EE_c =
      limitRate(max_translational_velocity, max_translational_acceleration, max_translational_jerk,
                kFactorCartesianRotationPoseInterface * max_rotational_velocity,
                kFactorCartesianRotationPoseInterface * max_rotational_acceleration,
                kFactorCartesianRotationPoseInterface * max_rotational_jerk, commanded_O_dP_EE_c,
                last_O_dP_EE_c, last_O_ddP_EE_c);
  dx = Eigen::Matrix<double, 6, 1>(commanded_O_dP_EE_c.data());

  // Integrate limited twist
  limited_commanded_pose.translation() << last_commanded_pose.translation() + dx.head(3) * kDeltaT;
  limited_commanded_pose.linear() << last_commanded_pose.linear();
  if (dx.tail(3).norm() > kNormEps) {
    Eigen::Matrix3d omega_skew;
    Eigen::Vector3d w_norm(dx.tail(3) / dx.tail(3).norm());
    double theta = kDeltaT * dx.tail(3).norm();
    omega_skew << 0, -w_norm(2), w_norm(1), w_norm(2), 0, -w_norm(0), -w_norm(1), w_norm(0), 0;
    // NOLINTNEXTLINE(readability-identifier-naming)
    Eigen::Matrix3d R = Eigen::Matrix3d::Identity() + sin(theta) * omega_skew +
                        (1.0 - cos(theta)) * (omega_skew * omega_skew);
    limited_commanded_pose.linear() << R * last_commanded_pose.linear();
  }

  std::array<double, 16> limited_values{};
  Eigen::Map<Eigen::Matrix4d>(&limited_values[0], 4, 4) = limited_commanded_pose.matrix();
  return limited_values;
}

}  // namespace franka
<|endoftext|>