<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_LINUX_LINUX_HH__
#define __ARCH_ARM_LINUX_LINUX_HH__

#include "kern/linux/linux.hh"

class ArmLinux : public Linux
{
  public:

    /// This table maps the target open() flags to the corresponding
    /// host open() flags.
    static OpenFlagTransTable openFlagTable[];

    /// Number of entries in openFlagTable[].
    static const int NUM_OPEN_FLAGS;

    //@{
    /// open(2) flag values.
    static const int TGT_O_RDONLY    = 00000000; //!< O_RDONLY
    static const int TGT_O_WRONLY    = 00000001; //!< O_WRONLY
    static const int TGT_O_RDWR      = 00000002; //!< O_RDWR
    static const int TGT_O_CREAT     = 00000100; //!< O_CREAT
    static const int TGT_O_EXCL      = 00000200; //!< O_EXCL
    static const int TGT_O_NOCTTY    = 00000400; //!< O_NOCTTY
    static const int TGT_O_TRUNC     = 00001000; //!< O_TRUNC
    static const int TGT_O_APPEND    = 00002000; //!< O_APPEND
    static const int TGT_O_NONBLOCK  = 00004000; //!< O_NONBLOCK
    static const int TGT_O_SYNC      = 00010000; //!< O_SYNC
    static const int TGT_FASYNC      = 00020000; //!< FASYNC
    static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY
    static const int TGT_O_NOFOLLOW  = 00100000; //!< O_NOFOLLOW
    static const int TGT_O_DIRECT    = 00200000; //!< O_DIRECT
    static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE
    static const int TGT_O_NOATIME   = 01000000; //!< O_NOATIME
    //@}

    /// For mmap().
    static const unsigned TGT_MAP_ANONYMOUS = 0x800;

    //@{
    /// For getsysinfo().
    static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
    static const unsigned GSI_CPU_INFO = 59;       //!< CPU information
    static const unsigned GSI_PROC_TYPE = 60;      //!< get proc_type
    static const unsigned GSI_MAX_CPU = 30;        //!< max # cpu's on this machine
    static const unsigned GSI_CPUS_IN_BOX = 55;    //!< number of CPUs in system
    static const unsigned GSI_PHYSMEM = 19;        //!< Physical memory in KB
    static const unsigned GSI_CLK_TCK = 42;        //!< clock freq in Hz
    //@}

    //@{
    /// For getrusage().
    static const int TGT_RUSAGE_SELF = 0;
    static const int TGT_RUSAGE_CHILDREN = -1;
    static const int TGT_RUSAGE_BOTH = -2;
    //@}

    //@{
    /// For setsysinfo().
    static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
    //@}

    //@{
    /// ioctl() command codes.
    static const unsigned TIOCGETP_   = 0x40067408;
    static const unsigned TIOCSETP_   = 0x80067409;
    static const unsigned TIOCSETN_   = 0x8006740a;
    static const unsigned TIOCSETC_   = 0x80067411;
    static const unsigned TIOCGETC_   = 0x40067412;
    static const unsigned FIONREAD_   = 0x4004667f;
    static const unsigned TIOCISATTY_ = 0x2000745e;
    static const unsigned TIOCGETS_   = 0x402c7413;
    static const unsigned TIOCGETA_   = 0x40127417;
    //@}

    /// For table().
    static const int TBL_SYSINFO = 12;

    /// Resource enumeration for getrlimit().
    enum rlimit_resources {
        TGT_RLIMIT_CPU = 0,
        TGT_RLIMIT_FSIZE = 1,
        TGT_RLIMIT_DATA = 2,
        TGT_RLIMIT_STACK = 3,
        TGT_RLIMIT_CORE = 4,
        TGT_RLIMIT_NOFILE = 5,
        TGT_RLIMIT_AS = 6,
        TGT_RLIMIT_RSS = 7,
        TGT_RLIMIT_VMEM = 7,
        TGT_RLIMIT_NPROC = 8,
        TGT_RLIMIT_MEMLOCK = 9,
        TGT_RLIMIT_LOCKS = 10
    };

    typedef struct {
        uint32_t st_dev;
        uint32_t st_ino;
        uint16_t st_mode;
        uint16_t st_nlink;
        uint16_t st_uid;
        uint16_t st_gid;
        uint32_t st_rdev;
        uint32_t st_size;
        uint32_t st_blksize;
        uint32_t st_blocks;
        uint32_t st_atimeX;
        uint32_t st_atime_nsec;
        uint32_t st_mtimeX;
        uint32_t st_mtime_nsec;
        uint32_t st_ctimeX;
        uint32_t st_ctime_nsec;
    } tgt_stat;

    typedef struct {
        uint64_t  st_dev;
        uint8_t   __pad0[4];
        uint32_t  __st_ino;
        uint32_t  st_mode;
        uint32_t  st_nlink;
        uint32_t  st_uid;
        uint32_t  st_gid;
        uint64_t  st_rdev;
        uint8_t   __pad3[4];
        int64_t   __attribute__ ((aligned (8))) st_size;
        uint32_t  st_blksize;
        uint64_t  __attribute__ ((aligned (8))) st_blocks;
        uint32_t  st_atimeX;
        uint32_t  st_atime_nsec;
        uint32_t  st_mtimeX;
        uint32_t  st_mtime_nsec;
        uint32_t  st_ctimeX;
        uint32_t  st_ctime_nsec;
        uint64_t  st_ino;
    } tgt_stat64;

};

#endif
<commit_msg>ARM: Update some syscall constants and delete others that are Alpha only.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_LINUX_LINUX_HH__
#define __ARCH_ARM_LINUX_LINUX_HH__

#include "kern/linux/linux.hh"

class ArmLinux : public Linux
{
  public:

    /// This table maps the target open() flags to the corresponding
    /// host open() flags.
    static OpenFlagTransTable openFlagTable[];

    /// Number of entries in openFlagTable[].
    static const int NUM_OPEN_FLAGS;

    //@{
    /// open(2) flag values.
    static const int TGT_O_RDONLY    = 00000000; //!< O_RDONLY
    static const int TGT_O_WRONLY    = 00000001; //!< O_WRONLY
    static const int TGT_O_RDWR      = 00000002; //!< O_RDWR
    static const int TGT_O_CREAT     = 00000100; //!< O_CREAT
    static const int TGT_O_EXCL      = 00000200; //!< O_EXCL
    static const int TGT_O_NOCTTY    = 00000400; //!< O_NOCTTY
    static const int TGT_O_TRUNC     = 00001000; //!< O_TRUNC
    static const int TGT_O_APPEND    = 00002000; //!< O_APPEND
    static const int TGT_O_NONBLOCK  = 00004000; //!< O_NONBLOCK
    static const int TGT_O_SYNC      = 00010000; //!< O_SYNC
    static const int TGT_FASYNC      = 00020000; //!< FASYNC
    static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY
    static const int TGT_O_NOFOLLOW  = 00100000; //!< O_NOFOLLOW
    static const int TGT_O_DIRECT    = 00200000; //!< O_DIRECT
    static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE
    static const int TGT_O_NOATIME   = 01000000; //!< O_NOATIME
    //@}

    /// For mmap().
    static const unsigned TGT_MAP_ANONYMOUS = 0x20;

    //@{
    /// For getrusage().
    static const int TGT_RUSAGE_SELF = 0;
    static const int TGT_RUSAGE_CHILDREN = -1;
    static const int TGT_RUSAGE_BOTH = -2;
    //@}

    //@{
    /// ioctl() command codes.
    static const unsigned TIOCGETP_   = 0x40067408;
    static const unsigned TIOCSETP_   = 0x80067409;
    static const unsigned TIOCSETN_   = 0x8006740a;
    static const unsigned TIOCSETC_   = 0x80067411;
    static const unsigned TIOCGETC_   = 0x40067412;
    static const unsigned FIONREAD_   = 0x4004667f;
    static const unsigned TIOCISATTY_ = 0x2000745e;
    static const unsigned TIOCGETS_   = 0x402c7413;
    static const unsigned TIOCGETA_   = 0x40127417;
    //@}

    /// For table().
    static const int TBL_SYSINFO = 12;

    /// Resource enumeration for getrlimit().
    enum rlimit_resources {
        TGT_RLIMIT_CPU = 0,
        TGT_RLIMIT_FSIZE = 1,
        TGT_RLIMIT_DATA = 2,
        TGT_RLIMIT_STACK = 3,
        TGT_RLIMIT_CORE = 4,
        TGT_RLIMIT_RSS = 5,
        TGT_RLIMIT_NPROC = 6,
        TGT_RLIMIT_NOFILE = 7,
        TGT_RLIMIT_MEMLOCK = 8,
        TGT_RLIMIT_AS = 9,
        TGT_RLIMIT_LOCKS = 10
    };

    typedef struct {
        uint32_t st_dev;
        uint32_t st_ino;
        uint16_t st_mode;
        uint16_t st_nlink;
        uint16_t st_uid;
        uint16_t st_gid;
        uint32_t st_rdev;
        uint32_t st_size;
        uint32_t st_blksize;
        uint32_t st_blocks;
        uint32_t st_atimeX;
        uint32_t st_atime_nsec;
        uint32_t st_mtimeX;
        uint32_t st_mtime_nsec;
        uint32_t st_ctimeX;
        uint32_t st_ctime_nsec;
    } tgt_stat;

    typedef struct {
        uint64_t  st_dev;
        uint8_t   __pad0[4];
        uint32_t  __st_ino;
        uint32_t  st_mode;
        uint32_t  st_nlink;
        uint32_t  st_uid;
        uint32_t  st_gid;
        uint64_t  st_rdev;
        uint8_t   __pad3[4];
        int64_t   __attribute__ ((aligned (8))) st_size;
        uint32_t  st_blksize;
        uint64_t  __attribute__ ((aligned (8))) st_blocks;
        uint32_t  st_atimeX;
        uint32_t  st_atime_nsec;
        uint32_t  st_mtimeX;
        uint32_t  st_mtime_nsec;
        uint32_t  st_ctimeX;
        uint32_t  st_ctime_nsec;
        uint64_t  st_ino;
    } tgt_stat64;

};

#endif
<|endoftext|>


<commit_before>#ifndef DORY_PROCESS_SPAWN_H_
#define DORY_PROCESS_SPAWN_H_

#include <cstdio>
#include <cassert>
#include <functional>
#include <iostream>
#include <sstream>
#include <map>

#include "uv.h"

namespace spawn {
using namespace std;

// Forward declaration
class DoryProcessSpawn;

#if defined(NDEBUG)
# define ASSERT(exp)
#else
# define ASSERT(exp)  assert(exp)
#endif

template<class... T>
using Callback = std::map<std::string, std::function<void(T...)>>;

static uv_alloc_cb uvAllocCb = [](uv_handle_t* handle, size_t size, uv_buf_t* buf) {
  buf->base = (char*)malloc(size);
  buf->len = size;
};

class DoryProcessSpawn {
public:
  DoryProcessSpawn(char** args) : DoryProcessSpawn(uv_default_loop(), args) {}
  DoryProcessSpawn(uv_loop_t *loop,
                     char** args,
                     const char* cwd = NULL,
                     char** env = NULL) {
    this->uv_loop = loop;
    process.data = this;
    pipeOut.data = this;
    pipeErr.data = this;
    timer.data = this;

    uv_pipe_init(uv_loop, &pipeOut, 0);
    uv_pipe_init(uv_loop, &pipeErr, 0);

    options.stdio = stdio;
    options.stdio[0].flags = UV_IGNORE; // FIXME : supports input
    options.stdio[1].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    options.stdio[1].data.stream = (uv_stream_t*)&pipeOut;
    options.stdio[2].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    options.stdio[2].data.stream = (uv_stream_t*)&pipeErr;
    options.stdio_count = 3;
    options.cwd = cwd;
    options.env = env;

    options.exit_cb = [](uv_process_t *req, int64_t exit_status, int term_signal) {
      DoryProcessSpawn *child = (DoryProcessSpawn*)req->data;
      if (child->timer.loop == child->uv_loop) // which is initialized
        child->_clearTimer();

      uv_close((uv_handle_t*) req, NULL);
      uv_close((uv_handle_t*)&child->pipeOut, [](uv_handle_t*){});
      uv_close((uv_handle_t*)&child->pipeErr, [](uv_handle_t*){});

      child->emit("exit", exit_status, term_signal);
    };

    this->args = args;
    options.file = args[0];
    options.args = args;
  }

  DoryProcessSpawn& kill(int term_signal = 9) {
    uv_process_kill(&process, term_signal);
    return *this;
  }

  // FIXME : look ugly
  // work around emit and on.
  DoryProcessSpawn& emit(const string name, int64_t exit_status, int term_signal) {
    if (name.compare("exit") == 0 && exitCallback != nullptr)
      exitCallback(exit_status, term_signal);
    return *this;
  }
  DoryProcessSpawn& emit(const string name, char* buf, ssize_t nread) {
    if (name.compare("stdout") == 0 && stdoutCallback != nullptr)
      stdoutCallback(buf, nread);
    if (name.compare("stderr") == 0 && stderrCallback != nullptr)
      stderrCallback(buf, nread);
    return *this;
  }
  DoryProcessSpawn& emit(const string name, const char* _name, const char* message) {
    if (name.compare("error") == 0 && exitCallback != nullptr)
      errorCallback(_name, message);
    return *this;
  }

  //FIXME : variadic ..Args using tuple.
  template <typename... Args>
  DoryProcessSpawn& emit(const string name, Args&&... args) {
    if (eventListeners.count(name))
      eventListeners[name]();

    return *this;
  }

  DoryProcessSpawn& on(const string name, std::function<void(const char*, const char*)> func) {
    if (name.compare("error") == 0)
      errorCallback = func;

    return *this;
  }
  DoryProcessSpawn& on(const string name, std::function<void(int64_t,int)> func) {
    if (name.compare("exit") == 0)
      exitCallback = func;

    return *this;
  }
  DoryProcessSpawn& on(const string name, std::function<void(char*,ssize_t)> func) {
    if (name.compare("stdout") == 0)
      stdoutCallback = func;
    else if (name.compare("stderr") == 0)
        stderrCallback = func;

    return *this;
  }
  template <typename... Args>
  DoryProcessSpawn& on(const string name, std::function<void(Args...)> func) {
    eventListeners[name] = func;

    return *this;
  }
  DoryProcessSpawn& on(const string name, std::function<void()> func) {
    eventListeners[name] = func;

    return *this;
  }
  int spawn() {
    int r;

    if (timeout > 0) {
      r = uv_timer_init(uv_loop, &timer);
      ASSERT(r == 0);
      r = uv_timer_start(&timer, [](uv_timer_t* timer){
        DoryProcessSpawn *child = (DoryProcessSpawn*)timer->data;
        child->_clearTimer();

        uv_process_kill(&child->process, SIGKILL);

        child->emit("timeout");
      }, timeout, 0);
      ASSERT(r == 0);
    }

    r = uv_spawn(uv_loop, &process, &options);
    if (r != 0) // spawn error.
      return r;

    // stdout pipe
    r = uv_read_start((uv_stream_t*) &pipeOut, uvAllocCb, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
      DoryProcessSpawn *child = (DoryProcessSpawn*)stream->data;
      if (nread > 0) {
        child->emit("stdout", buf->base, nread);
      } else if (nread < 0) {
        if (nread != UV_EOF)
          child->kill(SIGTERM);
        //assert(nread == UV_EOF);
      }
      free(buf->base);
    });
    if (r != 0) { // stdout pipe error.
      kill();
      return r;
    }

    // stderr pipe
    r = uv_read_start((uv_stream_t*) &pipeErr, uvAllocCb, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
      DoryProcessSpawn *child = (DoryProcessSpawn*)stream->data;
      if (nread > 0) {
        child->emit("stderr", buf->base, nread);
      } else if (nread < 0) {
        if (nread != UV_EOF)
          child->kill(SIGTERM);
        //assert(nread == UV_EOF);
      }
      free(buf->base);
    });
    if (r != 0) { // stderr pipe error.
      kill();
      return r;
    }

    // everything is ok
    return 0;
  }

  int getPid() {
    return this->process.pid;
  }

  unsigned int timeout = 0; // forever in defaults
private:
  uv_loop_t* uv_loop;
  uv_process_t process;
  uv_process_options_t options = {0};
  uv_stdio_container_t stdio[3];
  char** args;
  uv_pipe_t pipeOut; // stdout
  uv_pipe_t pipeErr; // stderr
  uv_timer_t timer;

  Callback<> eventListeners;
  std::function<void(const char*, const char*)> errorCallback = nullptr;
  std::function<void(int64_t,int)> exitCallback = nullptr;
  std::function<void(char*, ssize_t)> stdoutCallback = nullptr;
  std::function<void(char*, ssize_t)> stderrCallback = nullptr;

  void _clearTimer() {
    if (!uv_is_closing((uv_handle_t*)&this->timer)) {
      uv_close((uv_handle_t*)&this->timer, [](uv_handle_t*){});
    }
  }
};

} // namespace spawn

#endif // DORY_PROCESS_SPAWN_H_<commit_msg>clean up the eventListeners in destructor<commit_after>#ifndef DORY_PROCESS_SPAWN_H_
#define DORY_PROCESS_SPAWN_H_

#include <cstdio>
#include <cassert>
#include <functional>
#include <iostream>
#include <sstream>
#include <map>

#include "uv.h"

namespace spawn {
using namespace std;

// Forward declaration
class DoryProcessSpawn;

#if defined(NDEBUG)
# define ASSERT(exp)
#else
# define ASSERT(exp)  assert(exp)
#endif

template<class... T>
using Callback = std::map<std::string, std::function<void(T...)>>;

static uv_alloc_cb uvAllocCb = [](uv_handle_t* handle, size_t size, uv_buf_t* buf) {
  buf->base = (char*)malloc(size);
  buf->len = size;
};

class DoryProcessSpawn {
public:
  DoryProcessSpawn(char** args) : DoryProcessSpawn(uv_default_loop(), args) {}
  DoryProcessSpawn(uv_loop_t *loop,
                     char** args,
                     const char* cwd = NULL,
                     char** env = NULL) {
    this->uv_loop = loop;
    process.data = this;
    pipeOut.data = this;
    pipeErr.data = this;
    timer.data = this;

    uv_pipe_init(uv_loop, &pipeOut, 0);
    uv_pipe_init(uv_loop, &pipeErr, 0);

    options.stdio = stdio;
    options.stdio[0].flags = UV_IGNORE; // FIXME : supports input
    options.stdio[1].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    options.stdio[1].data.stream = (uv_stream_t*)&pipeOut;
    options.stdio[2].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
    options.stdio[2].data.stream = (uv_stream_t*)&pipeErr;
    options.stdio_count = 3;
    options.cwd = cwd;
    options.env = env;

    options.exit_cb = [](uv_process_t *req, int64_t exit_status, int term_signal) {
      DoryProcessSpawn *child = (DoryProcessSpawn*)req->data;
      if (child->timer.loop == child->uv_loop) // which is initialized
        child->_clearTimer();

      uv_close((uv_handle_t*) req, NULL);
      uv_close((uv_handle_t*)&child->pipeOut, [](uv_handle_t*){});
      uv_close((uv_handle_t*)&child->pipeErr, [](uv_handle_t*){});

      child->emit("exit", exit_status, term_signal);
    };

    this->args = args;
    options.file = args[0];
    options.args = args;
  }
  ~DoryProcessSpawn() {
    eventListeners.clear();
  }

  DoryProcessSpawn& kill(int term_signal = 9) {
    uv_process_kill(&process, term_signal);
    return *this;
  }

  // FIXME : look ugly
  // work around emit and on.
  DoryProcessSpawn& emit(const string name, int64_t exit_status, int term_signal) {
    if (name.compare("exit") == 0 && exitCallback != nullptr)
      exitCallback(exit_status, term_signal);
    return *this;
  }
  DoryProcessSpawn& emit(const string name, char* buf, ssize_t nread) {
    if (name.compare("stdout") == 0 && stdoutCallback != nullptr)
      stdoutCallback(buf, nread);
    if (name.compare("stderr") == 0 && stderrCallback != nullptr)
      stderrCallback(buf, nread);
    return *this;
  }
  DoryProcessSpawn& emit(const string name, const char* _name, const char* message) {
    if (name.compare("error") == 0 && exitCallback != nullptr)
      errorCallback(_name, message);
    return *this;
  }

  //FIXME : variadic ..Args using tuple.
  template <typename... Args>
  DoryProcessSpawn& emit(const string name, Args&&... args) {
    if (eventListeners.count(name))
      eventListeners[name]();

    return *this;
  }

  DoryProcessSpawn& on(const string name, std::function<void(const char*, const char*)> func) {
    if (name.compare("error") == 0)
      errorCallback = func;

    return *this;
  }
  DoryProcessSpawn& on(const string name, std::function<void(int64_t,int)> func) {
    if (name.compare("exit") == 0)
      exitCallback = func;

    return *this;
  }
  DoryProcessSpawn& on(const string name, std::function<void(char*,ssize_t)> func) {
    if (name.compare("stdout") == 0)
      stdoutCallback = func;
    else if (name.compare("stderr") == 0)
        stderrCallback = func;

    return *this;
  }
  template <typename... Args>
  DoryProcessSpawn& on(const string name, std::function<void(Args...)> func) {
    eventListeners[name] = func;

    return *this;
  }
  DoryProcessSpawn& on(const string name, std::function<void()> func) {
    eventListeners[name] = func;

    return *this;
  }
  int spawn() {
    int r;

    if (timeout > 0) {
      r = uv_timer_init(uv_loop, &timer);
      ASSERT(r == 0);
      r = uv_timer_start(&timer, [](uv_timer_t* timer){
        DoryProcessSpawn *child = (DoryProcessSpawn*)timer->data;
        child->_clearTimer();

        uv_process_kill(&child->process, SIGKILL);

        child->emit("timeout");
      }, timeout, 0);
      ASSERT(r == 0);
    }

    r = uv_spawn(uv_loop, &process, &options);
    if (r != 0) // spawn error.
      return r;

    // stdout pipe
    r = uv_read_start((uv_stream_t*) &pipeOut, uvAllocCb, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
      DoryProcessSpawn *child = (DoryProcessSpawn*)stream->data;
      if (nread > 0) {
        child->emit("stdout", buf->base, nread);
      } else if (nread < 0) {
        if (nread != UV_EOF)
          child->kill(SIGTERM);
        //assert(nread == UV_EOF);
      }
      free(buf->base);
    });
    if (r != 0) { // stdout pipe error.
      kill();
      return r;
    }

    // stderr pipe
    r = uv_read_start((uv_stream_t*) &pipeErr, uvAllocCb, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
      DoryProcessSpawn *child = (DoryProcessSpawn*)stream->data;
      if (nread > 0) {
        child->emit("stderr", buf->base, nread);
      } else if (nread < 0) {
        if (nread != UV_EOF)
          child->kill(SIGTERM);
        //assert(nread == UV_EOF);
      }
      free(buf->base);
    });
    if (r != 0) { // stderr pipe error.
      kill();
      return r;
    }

    // everything is ok
    return 0;
  }

  int getPid() {
    return this->process.pid;
  }

  unsigned int timeout = 0; // forever in defaults
private:
  uv_loop_t* uv_loop;
  uv_process_t process;
  uv_process_options_t options = {0};
  uv_stdio_container_t stdio[3];
  char** args;
  uv_pipe_t pipeOut; // stdout
  uv_pipe_t pipeErr; // stderr
  uv_timer_t timer;

  Callback<> eventListeners;
  std::function<void(const char*, const char*)> errorCallback = nullptr;
  std::function<void(int64_t,int)> exitCallback = nullptr;
  std::function<void(char*, ssize_t)> stdoutCallback = nullptr;
  std::function<void(char*, ssize_t)> stderrCallback = nullptr;

  void _clearTimer() {
    if (!uv_is_closing((uv_handle_t*)&this->timer)) {
      uv_close((uv_handle_t*)&this->timer, [](uv_handle_t*){});
    }
  }
};

} // namespace spawn

#endif // DORY_PROCESS_SPAWN_H_<|endoftext|>


<commit_before>#include "ts_packet.h"

TS_Packet::TS_Packet() {
  Clear( );
}

TS_Packet::TS_Packet( std::string & Data ) {
  if( Data.size() < 188 ) {
    Clear( );
  } else {
    for( int i = 0; i < 188; i++ ) {
      Buffer[i] = Data[i];
    }
    Data.erase(0,188);
    Free = 0;
  }
}

TS_Packet::~TS_Packet() { }

void TS_Packet::PID( int NewVal ) {
  Buffer[1] = (Buffer[1] & 0xE0) + ((NewVal & 0x1F00) >> 8 );
  Buffer[2] = (NewVal & 0x00FF);
  Free = std::min( Free, 185 );
}

int TS_Packet::PID() {
  return (( Buffer[1] & 0x1F ) << 8 ) + Buffer[2];
}

void TS_Packet::ContinuityCounter( int NewVal ) {
  Buffer[3] = ( Buffer[3] & 0xF0 ) + ( NewVal & 0x0F );
  Free = std::min( Free, 184 );
}

int TS_Packet::ContinuityCounter() {
  return ( Buffer[3] & 0x0F );
}

int TS_Packet::BytesFree( ) {
  return Free;
}

void TS_Packet::Clear( ) {
  Free = 187;
  Buffer[0] = 0x47;
  for( int i = 1; i < 188; i++ ) {
    Buffer[i] = 0x00;
  }
}

void TS_Packet::AdaptionField( int NewVal ) {
  NewVal = NewVal % 4;
  NewVal = NewVal << 4;
  Buffer[3] = ( Buffer[3] & 0xCF ) + NewVal;
}

int TS_Packet::AdaptionField( ) {
  return ((Buffer[3] & 0x30) >> 4 ) >= 2;
}

void TS_Packet::PCR( int64_t NewVal ) {
  Buffer[3] = (Buffer[3] | 0x30);
  Buffer[4] = 7;
  Buffer[5] = (Buffer[5] | 0x10 );
  int64_t TmpVal = NewVal / 300;
  Buffer[6] = (((TmpVal>>1)>>24) & 0xFF);
  Buffer[7] = (((TmpVal>>1)>>16) & 0xFF);
  Buffer[8] = (((TmpVal>>1)>>8) & 0xFF);
  Buffer[9] = ((TmpVal>>1) & 0xFF);
  int Remainder = NewVal % 300;
  Buffer[10] = 0x7E + ((TmpVal & 0x01)<<7) + ((Remainder & 0x0100) >> 8 );
  Buffer[11] = (Remainder & 0x00FF);
  Free = std::min( Free, 176 );
};

int64_t TS_Packet::PCR( ) {
  if( !AdaptionField() ) {
    return -1;
  }
  if( !(Buffer[5] & 0x10 ) ) {
    return -1;
  }
  int64_t Result = 0;
  Result = (((((((Buffer[6] << 8) + Buffer[7]) << 8) + Buffer[8]) << 8) + Buffer[9]) << 1) + ( Buffer[10] & 0x80 );
  Result = Result * 300;
  Result += ((Buffer[10] & 0x01) << 8 + Buffer[11]);
  return Result;
}

int TS_Packet::AdaptionFieldLen( ) {
  if( !AdaptionField() ) {
    return -1;
  }
  return (int)Buffer[4];
}

void TS_Packet::Print( ) {
  std::cout << "TS Packet: " << (Buffer[0] == 0x47)
            << "\n\tNewUnit: " << UnitStart()
            << "\n\tPID: " << PID()
            << "\n\tContinuity Counter: " << ContinuityCounter()
            << "\n\tAdaption Field: " << AdaptionField() << "\n";
  if( AdaptionField() ) {
    std::cout << "\t\tAdaption Field Length: " << AdaptionFieldLen() << "\n";
    if( AdaptionFieldLen() ) {
      std::cout << "\t\tRandom Access: " << RandomAccess() << "\n";
    }
    if( PCR() != -1 ) {
      std::cout << "\t\tPCR: " << PCR() << "( " << (double)PCR() / 27000000 << " s )\n";
    }
  }
}

int TS_Packet::UnitStart( ) {
  return ( Buffer[1] & 0x40) >> 6;
}

void TS_Packet::UnitStart( int NewVal ) {
  if( NewVal ) {
    Buffer[1] = (Buffer[1] | 0x40);
  } else {
    Buffer[1] = (Buffer[1] & 0xBF);
  }
}

int TS_Packet::RandomAccess( ) {
  if( !AdaptionField() ) {
    return -1;
  }
  return ( Buffer[5] & 0x40) >> 6;
}

void TS_Packet::RandomAccess( int NewVal ) {
  if( AdaptionField() ) {
    if( NewVal ) {
      Buffer[5] = (Buffer[5] | 0x40);
    } else {
      Buffer[5] = (Buffer[5] & 0xBF);
    }
  } else {
    Buffer[3] = (Buffer[3] | 0x30);
    Buffer[4] = 1;
    if( NewVal ) {
      Buffer[5] = 0x40;
    } else {
      Buffer[5] = 0x00;
    }
    Free = 183;
  }
}

void TS_Packet::DefaultPAT( ) {
  static int MyCntr = 0;
  UnitStart( 1 );
  PID( 0 );
  ContinuityCounter( MyCntr );
  AdaptionField( 0x01 );
  Buffer[ 4] = 0x00;//Pointer Field
  Buffer[ 5] = 0x00;//TableID
  Buffer[ 6] = 0xB0,//Reserved + SectionLength
  Buffer[ 7] = 0x0D;//SectionLength (Cont)
  Buffer[ 8] = 0x00;//Transport_Stream_ID
  Buffer[ 9] = 0x01;//Transport_Stream_ID (Cont)
  Buffer[10] = 0xC1;//Reserved + VersionNumber + Current_Next_Indicator
  Buffer[11] = 0x00;//Section_Number
  Buffer[12] = 0x00;//Last_Section_Number
  Buffer[13] = 0x00;  //Program Number
  Buffer[14] = 0x01;  //Program Number (Cont)
  Buffer[15] = 0xF0;  //Reserved + Program_Map_PID
  Buffer[16] = 0x00;  //Program_Map_PID (Cont)
  Buffer[17] = 0x2A;//CRC32
  Buffer[18] = 0xB1;//CRC32 (Cont)
  Buffer[19] = 0x04;//CRC32 (Cont)
  Buffer[20] = 0xB2;//CRC32 (Cont)
  std::fill( Buffer+21, Buffer+188, 0xFF );
  Free = 0;
  MyCntr = ( (MyCntr + 1) % 0xF);
}

void TS_Packet::DefaultPMT( ) {
  static int MyCntr = 0;
  UnitStart( 1 );
  PID( 0x1000 );
  ContinuityCounter( MyCntr );
  AdaptionField( 0x01 );
  Buffer[ 4] = 0x00;//Pointer Field
  Buffer[ 5] = 0x02;//TableID
  Buffer[ 6] = 0xb0;//Reserved + Section_Length
  Buffer[ 7] = 0x12;//Section_Length (Cont)
  Buffer[ 8] = 0x00;//Program_Number
  Buffer[ 9] = 0x01;//Program_Number (Cont)
  Buffer[10] = 0xc1;//Reserved + VersionNumber + Current_Next_Indicator
  Buffer[11] = 0x00;//Section_Number
  Buffer[12] = 0x00;//Last_Section_Number
  Buffer[13] = 0xe1;//Reserved + PCR_PID
  Buffer[14] = 0x00;//PCR_PID (Cont)
  Buffer[15] = 0xf0;//Reserved + Program_Info_Length
  Buffer[16] = 0x00;//Program_Info_Length (Cont)
  Buffer[17] = 0x1b;  //Stream_Type
  Buffer[18] = 0xe1;  //Reserved + Elementary_PID
  Buffer[19] = 0x00;  //Elementary_PID (Cont)
  Buffer[20] = 0xf0;  //Reserved + ES_Info_Length
  Buffer[21] = 0x00;  //ES_Info_Length (Cont)
  Buffer[22] = 0x15;//CRC32
  Buffer[23] = 0xbd;//CRC32 (Cont)
  Buffer[24] = 0x4d;//CRC32 (Cont)
  Buffer[25] = 0x56;//CRC32 (Cont)
  std::fill( Buffer+26, Buffer+188, 0xFF );
  Free = 0;
  MyCntr = ( (MyCntr + 1) % 0xF);
}

std::string TS_Packet::ToString( ) {
  std::string Result( Buffer, 188 );
  return Result;
}

void TS_Packet::PESLeadIn( int NewLen ) {
  int Offset = ( 188 - Free );
  Buffer[Offset] = 0x00;//PacketStartCodePrefix
  Buffer[Offset+1] = 0x00;//PacketStartCodePrefix (Cont)
  Buffer[Offset+2] = 0x01;//PacketStartCodePrefix (Cont)
  Buffer[Offset+3] = 0xe0;//StreamType Video
  Buffer[Offset+4] = (NewLen & 0xFF00) >> 8;//PES PacketLength
  Buffer[Offset+5] = (NewLen & 0x00FF);//PES PacketLength (Cont)
  Buffer[Offset+6] = 0x80;//Reserved + Flags
  Buffer[Offset+7] = 0x80;//PTSOnlyFlag + Flags
  Buffer[Offset+8] = 0x05;//PESHeaderDataLength
  Buffer[Offset+9] = 0x20 + ((PCR() & 0x1C0000000) >> 29 ) + 1;//PTS
  Buffer[Offset+10] = 0x00 + ((PCR() & 0x03FC00000) >> 22 );//PTS (Cont)
  Buffer[Offset+11] = 0x00 + ((PCR() & 0x0003F8000) >> 14 ) + 1;//PTS (Cont)
  Buffer[Offset+12] = 0x00 + ((PCR() & 0x000008F10) >> 7 );//PTS (Cont)
  Buffer[Offset+13] = 0x00 + ((PCR() & 0x0000000EF) << 1) + 1;//PTS (Cont)

  //PesPacket-Wise Prepended Data

  Buffer[Offset+14] = 0x00;//NALU StartCode
  Buffer[Offset+15] = 0x00;//NALU StartCode (Cont)
  Buffer[Offset+16] = 0x00;//NALU StartCode (Cont)
  Buffer[Offset+17] = 0x01;//NALU StartCode (Cont)
  Buffer[Offset+18] = 0x09;//NALU EndOfPacket (Einde Vorige Packet)
  Buffer[Offset+19] = 0xF0;//NALU EndOfPacket (Cont)
  Free = Free - 20;
  fprintf( stderr, "\tAdding PES Lead In with Offset %d and Size %d\n", Offset, NewLen );
  fprintf( stderr, "\t\tNew Free is %d\n", Free );
}

void TS_Packet::FillFree( std::string & NewVal ) {
  int Offset = (188 - Free);
  for( int i = 0; (Offset + i) < 188; i++ ) {
    Buffer[Offset+i] = NewVal[i];
  }
  NewVal.erase(0,Free);
  Free = 0;
}

void TS_Packet::AddStuffing( int NumBytes ) {
  if( NumBytes < 0 ) { return; }
  if( AdaptionField( ) == 3 ) {
    int Offset = Buffer[4];
    Buffer[4] = Offset + NumBytes - 1;
    for( int i = 0; i < ( NumBytes -2 ); i ++ ) {
      Buffer[Offset+i] = 0xFF;
    }
    Free -= NumBytes;
  } else {
    AdaptionField( 3 );
    Buffer[4] = NumBytes - 1;
    Buffer[5] = 0x00;
    for( int i = 0; i < ( NumBytes -2 ); i ++ ) {
      Buffer[6+i] = 0xFF;
    }
    Free -= NumBytes;
  }
}
<commit_msg>Working video, though with some glitches, probably due to inconsistency in PTS increases<commit_after>#include "ts_packet.h"

TS_Packet::TS_Packet() {
  Clear( );
}

TS_Packet::TS_Packet( std::string & Data ) {
  if( Data.size() < 188 ) {
    Clear( );
  } else {
    for( int i = 0; i < 188; i++ ) {
      Buffer[i] = Data[i];
    }
    Data.erase(0,188);
    Free = 0;
  }
}

TS_Packet::~TS_Packet() { }

void TS_Packet::PID( int NewVal ) {
  Buffer[1] = (Buffer[1] & 0xE0) + ((NewVal & 0x1F00) >> 8 );
  Buffer[2] = (NewVal & 0x00FF);
  Free = std::min( Free, 185 );
}

int TS_Packet::PID() {
  return (( Buffer[1] & 0x1F ) << 8 ) + Buffer[2];
}

void TS_Packet::ContinuityCounter( int NewVal ) {
  Buffer[3] = ( Buffer[3] & 0xF0 ) + ( NewVal & 0x0F );
  Free = std::min( Free, 184 );
}

int TS_Packet::ContinuityCounter() {
  return ( Buffer[3] & 0x0F );
}

int TS_Packet::BytesFree( ) {
  return Free;
}

void TS_Packet::Clear( ) {
  Free = 187;
  Buffer[0] = 0x47;
  for( int i = 1; i < 188; i++ ) {
    Buffer[i] = 0x00;
  }
  AdaptionField( 1 );
}

void TS_Packet::AdaptionField( int NewVal ) {
  NewVal = NewVal % 4;
  NewVal = NewVal << 4;
  Buffer[3] = ( Buffer[3] & 0xCF ) + NewVal;
  Free = std::min( Free, 184 );
}

int TS_Packet::AdaptionField( ) {
  return ((Buffer[3] & 0x30) >> 4 ) >= 2;
}

void TS_Packet::PCR( int64_t NewVal ) {
  NewVal += (0xF618 * 300);
  Buffer[3] = (Buffer[3] | 0x30);
  Buffer[4] = 7;
  Buffer[5] = (Buffer[5] | 0x10 );
  int64_t TmpVal = NewVal / 300;
  Buffer[6] = (((TmpVal>>1)>>24) & 0xFF);
  Buffer[7] = (((TmpVal>>1)>>16) & 0xFF);
  Buffer[8] = (((TmpVal>>1)>>8) & 0xFF);
  Buffer[9] = ((TmpVal>>1) & 0xFF);
  int Remainder = NewVal % 300;
  Buffer[10] = 0x7E + ((TmpVal & 0x01)<<7) + ((Remainder & 0x0100) >> 8 );
  Buffer[11] = (Remainder & 0x00FF);
  Free = std::min( Free, 176 );
};

int64_t TS_Packet::PCR( ) {
  if( !AdaptionField() ) {
    return -1;
  }
  if( !(Buffer[5] & 0x10 ) ) {
    return -1;
  }
  int64_t Result = 0;
  Result = (((((((Buffer[6] << 8) + Buffer[7]) << 8) + Buffer[8]) << 8) + Buffer[9]) << 1) + ( Buffer[10] & 0x80 );
  Result = Result * 300;
  Result += ((Buffer[10] & 0x01) << 8 + Buffer[11]);
  return Result;
}

int TS_Packet::AdaptionFieldLen( ) {
  if( !AdaptionField() ) {
    return -1;
  }
  return (int)Buffer[4];
}

void TS_Packet::Print( ) {
  std::cout << "TS Packet: " << (Buffer[0] == 0x47)
            << "\n\tNewUnit: " << UnitStart()
            << "\n\tPID: " << PID()
            << "\n\tContinuity Counter: " << ContinuityCounter()
            << "\n\tAdaption Field: " << AdaptionField() << "\n";
  if( AdaptionField() ) {
    std::cout << "\t\tAdaption Field Length: " << AdaptionFieldLen() << "\n";
    if( AdaptionFieldLen() ) {
      std::cout << "\t\tRandom Access: " << RandomAccess() << "\n";
    }
    if( PCR() != -1 ) {
      std::cout << "\t\tPCR: " << PCR() << "( " << (double)PCR() / 27000000 << " s )\n";
    }
  }
}

int TS_Packet::UnitStart( ) {
  return ( Buffer[1] & 0x40) >> 6;
}

void TS_Packet::UnitStart( int NewVal ) {
  if( NewVal ) {
    Buffer[1] = (Buffer[1] | 0x40);
  } else {
    Buffer[1] = (Buffer[1] & 0xBF);
  }
}

int TS_Packet::RandomAccess( ) {
  if( !AdaptionField() ) {
    return -1;
  }
  return ( Buffer[5] & 0x40) >> 6;
}

void TS_Packet::RandomAccess( int NewVal ) {
  if( AdaptionField() ) {
    if( NewVal ) {
      Buffer[5] = (Buffer[5] | 0x40);
    } else {
      Buffer[5] = (Buffer[5] & 0xBF);
    }
  } else {
    Buffer[3] = (Buffer[3] | 0x30);
    Buffer[4] = 1;
    if( NewVal ) {
      Buffer[5] = 0x40;
    } else {
      Buffer[5] = 0x00;
    }
    Free = 183;
  }
}

void TS_Packet::DefaultPAT( ) {
  static int MyCntr = 0;
  UnitStart( 1 );
  PID( 0 );
  ContinuityCounter( MyCntr );
  AdaptionField( 0x01 );
  Buffer[ 4] = 0x00;//Pointer Field
  Buffer[ 5] = 0x00;//TableID
  Buffer[ 6] = 0xB0,//Reserved + SectionLength
  Buffer[ 7] = 0x0D;//SectionLength (Cont)
  Buffer[ 8] = 0x00;//Transport_Stream_ID
  Buffer[ 9] = 0x01;//Transport_Stream_ID (Cont)
  Buffer[10] = 0xC1;//Reserved + VersionNumber + Current_Next_Indicator
  Buffer[11] = 0x00;//Section_Number
  Buffer[12] = 0x00;//Last_Section_Number
  Buffer[13] = 0x00;  //Program Number
  Buffer[14] = 0x01;  //Program Number (Cont)
  Buffer[15] = 0xF0;  //Reserved + Program_Map_PID
  Buffer[16] = 0x00;  //Program_Map_PID (Cont)
  Buffer[17] = 0x2A;//CRC32
  Buffer[18] = 0xB1;//CRC32 (Cont)
  Buffer[19] = 0x04;//CRC32 (Cont)
  Buffer[20] = 0xB2;//CRC32 (Cont)
  std::fill( Buffer+21, Buffer+188, 0xFF );
  Free = 0;
  MyCntr = ( (MyCntr + 1) % 0xF);
}

void TS_Packet::DefaultPMT( ) {
  static int MyCntr = 0;
  UnitStart( 1 );
  PID( 0x1000 );
  ContinuityCounter( MyCntr );
  AdaptionField( 0x01 );
  Buffer[ 4] = 0x00;//Pointer Field
  Buffer[ 5] = 0x02;//TableID
  Buffer[ 6] = 0xb0;//Reserved + Section_Length
  Buffer[ 7] = 0x12;//Section_Length (Cont)
  Buffer[ 8] = 0x00;//Program_Number
  Buffer[ 9] = 0x01;//Program_Number (Cont)
  Buffer[10] = 0xc1;//Reserved + VersionNumber + Current_Next_Indicator
  Buffer[11] = 0x00;//Section_Number
  Buffer[12] = 0x00;//Last_Section_Number
  Buffer[13] = 0xe1;//Reserved + PCR_PID
  Buffer[14] = 0x00;//PCR_PID (Cont)
  Buffer[15] = 0xf0;//Reserved + Program_Info_Length
  Buffer[16] = 0x00;//Program_Info_Length (Cont)
  Buffer[17] = 0x1b;  //Stream_Type
  Buffer[18] = 0xe1;  //Reserved + Elementary_PID
  Buffer[19] = 0x00;  //Elementary_PID (Cont)
  Buffer[20] = 0xf0;  //Reserved + ES_Info_Length
  Buffer[21] = 0x00;  //ES_Info_Length (Cont)
  Buffer[22] = 0x15;//CRC32
  Buffer[23] = 0xbd;//CRC32 (Cont)
  Buffer[24] = 0x4d;//CRC32 (Cont)
  Buffer[25] = 0x56;//CRC32 (Cont)
  std::fill( Buffer+26, Buffer+188, 0xFF );
  Free = 0;
  MyCntr = ( (MyCntr + 1) % 0xF);
}

std::string TS_Packet::ToString( ) {
  std::string Result( Buffer, 188 );
  return Result;
}

void TS_Packet::PESLeadIn( int NewLen ) {
  static uint64_t PTS = 126000;
  NewLen += 14;
  int Offset = ( 188 - Free );
  Buffer[Offset] = 0x00;//PacketStartCodePrefix
  Buffer[Offset+1] = 0x00;//PacketStartCodePrefix (Cont)
  Buffer[Offset+2] = 0x01;//PacketStartCodePrefix (Cont)
  Buffer[Offset+3] = 0xe0;//StreamType Video
  Buffer[Offset+4] = (NewLen & 0xFF00) >> 8;//PES PacketLength
  Buffer[Offset+5] = (NewLen & 0x00FF);//PES PacketLength (Cont)
  Buffer[Offset+6] = 0x80;//Reserved + Flags
  Buffer[Offset+7] = 0x80;//PTSOnlyFlag + Flags
  Buffer[Offset+8] = 0x05;//PESHeaderDataLength
  Buffer[Offset+9] = 0x20 + ((PTS & 0x1C0000000) >> 29 ) + 1;//PTS
  Buffer[Offset+10] = 0x00 + ((PTS & 0x03FC00000) >> 22 );//PTS (Cont)
  Buffer[Offset+11] = 0x00 + ((PTS & 0x0003F8000) >> 14 ) + 1;//PTS (Cont)
  Buffer[Offset+12] = 0x00 + ((PTS & 0x000007F10) >> 7 );//PTS (Cont)
  Buffer[Offset+13] = 0x00 + ((PTS & 0x00000007F) << 1) + 1;//PTS (Cont)

  //PesPacket-Wise Prepended Data

  Buffer[Offset+14] = 0x00;//NALU StartCode
  Buffer[Offset+15] = 0x00;//NALU StartCode (Cont)
  Buffer[Offset+16] = 0x00;//NALU StartCode (Cont)
  Buffer[Offset+17] = 0x01;//NALU StartCode (Cont)
  Buffer[Offset+18] = 0x09;//NALU EndOfPacket (Einde Vorige Packet)
  Buffer[Offset+19] = 0xF0;//NALU EndOfPacket (Cont)
  Free = Free - 20;
  fprintf( stderr, "\tAdding PES Lead In with Offset %d and Size %d\n", Offset, NewLen );
  fprintf( stderr, "\t\tNew Free is %d\n", Free );
  PTS += 3003;
}

void TS_Packet::FillFree( std::string & NewVal ) {
  int Offset = (188 - Free);
  for( int i = 0; (Offset + i) < 188; i++ ) {
    Buffer[Offset+i] = NewVal[i];
  }
  NewVal.erase(0,Free);
  Free = 0;
}

void TS_Packet::AddStuffing( int NumBytes ) {
  if( NumBytes < 0 ) { return; }
  if( AdaptionField( ) == 3 ) {
    int Offset = Buffer[4];
    Buffer[4] = Offset + NumBytes - 1;
    for( int i = 0; i < ( NumBytes -2 ); i ++ ) {
      Buffer[Offset+i] = 0xFF;
    }
    Free -= NumBytes;
  } else {
    AdaptionField( 3 );
    Buffer[4] = NumBytes - 1;
    Buffer[5] = 0x00;
    for( int i = 0; i < ( NumBytes -2 ); i ++ ) {
      Buffer[6+i] = 0xFF;
    }
    Free -= NumBytes;
  }
}
<|endoftext|>


<commit_before>// $Header$

#include "TrackGL.h"
#include <Reve/Track.h>

#include <TGLDrawFlags.h>

#ifdef WIN32
#include "Windows4root.h"
#endif
#include <GL/gl.h>
#include <GL/glu.h>

using namespace Reve;

//______________________________________________________________________
// TrackGL
//

ClassImp(TrackGL)

TrackGL::TrackGL() : LineGL()
{
  // fCached = false; // Disable display list.
}

TrackGL::~TrackGL()
{}

/**************************************************************************/

Bool_t TrackGL::SetModel(TObject* obj)
{
  if(LineGL::SetModel(obj) == kFALSE) return kFALSE;
  if(SetModelCheckClass(obj, Track::Class())) {
    fTrack = dynamic_cast<Track*>(obj);
    return kTRUE;
  }
  return kFALSE;
}
/**************************************************************************/

void TrackGL::ProcessSelection(UInt_t* ptr, TGLViewer*, TGLScene*)
{
  // Processes secondary selection from TGLViewer.
  // Calls TPointSet3D::PointSelected(Int_t) with index of selected
  // point as an argument.

  Int_t n = ptr[0];
  printf("TrackGL::ProcessSelection %d names on the stack (z1=%g, z2=%g).\n",
	 n, Float_t(ptr[1])/0x7fffffff, Float_t(ptr[2])/0x7fffffff);
  ptr += 3;
  printf("  Names: ");
  for (Int_t j=0; j<n; ++j, ++ptr) printf ("%d ", *ptr);
  printf("\n");

  ((Track*)fM)->CtrlClicked((Track*)fM);
}

/**************************************************************************/
void TrackGL::DirectDraw(const TGLDrawFlags & flags) const
{
  // Render line and path marks

  LineGL::DirectDraw(flags);

  if ( ! fTrack->fPathMarks.empty()){

    TrackRnrStyle* rs = fTrack->GetRnrStyle();
    Int_t  style = rs->fPMStyle;

    UChar_t color[4];
    ColorFromIdx(rs->fPMColor, color);
    glColor4ubv(color);

    glPushAttrib(GL_POINT_BIT | GL_LINE_BIT | GL_ENABLE_BIT);
    glDisable(GL_LIGHTING);

    Int_t ms = rs->fPMStyle;
    // points
    if (ms != 2 && ms != 3 && ms != 5 && ms != 28)
    {
      Float_t size = 5*rs->fPMSize;
      if (style == 4 || style == 20 || style == 24)
      {
	if (style == 4 || style == 24)
	  glEnable(GL_BLEND);
	glEnable(GL_POINT_SMOOTH);
      }
      else
      {
	glDisable(GL_POINT_SMOOTH);
	if      (style == 1) size = 1;
	else if (style == 6) size = 2;
	else if (style == 7) size = 3;
      }
      glPointSize(size);

      glBegin(GL_POINTS);
      Bool_t accept;
      std::vector<PathMark*>& pm = fTrack->fPathMarks;
      for(std::vector<PathMark*>::iterator i=pm.begin(); i!=pm.end(); ++i)
      {
	accept = kFALSE;
	switch((*i)->type)
	{
	  case(PathMark::Daughter):
	    if(rs->fRnrDaughters) accept = kTRUE;
	    break;
	  case(PathMark::Reference):
	    if(rs->fRnrReferences) accept = kTRUE;
	    break;
	  case(PathMark::Decay):
	    if(rs->fRnrDecay) accept = kTRUE;
	    break;
	}
	if(accept)
	{
	  if((TMath::Abs((*i)->V.z) < rs->fMaxZ) && (*i)->V.Perp() < rs->fMaxR*rs->fMaxR)
	    glVertex3f((*i)->V.x, (*i)->V.y,(*i)->V.z);
	}
      }
      glEnd();
    } // end render points
    else
    {
      // crosses
      if ( style== 28)
      {
	glEnable(GL_BLEND);
	glEnable(GL_LINE_SMOOTH);
	glLineWidth(2);
      }
      else
      {
	glDisable(GL_LINE_SMOOTH);
      }

      glBegin(GL_LINES);
      Bool_t accept;
      Float_t d = 2* rs->fPMSize;
      Float_t p[3];
      std::vector<PathMark*>& pm = fTrack->fPathMarks;
      for(std::vector<PathMark*>::iterator i=pm.begin(); i!=pm.end(); ++i)
      {
	accept = kFALSE;
	switch((*i)->type)
	{
	  case(PathMark::Daughter):
	    if(rs->fRnrDaughters) accept = kTRUE;
	    break;
	  case(PathMark::Reference):
	    if(rs->fRnrReferences) accept = kTRUE;
	    break;
	  case(PathMark::Decay):
	    if(rs->fRnrDecay) accept = kTRUE;
	    break;
	}
	if(accept)
	{
	  if((TMath::Abs((*i)->V.z) < rs->fMaxZ) && (*i)->V.Perp() < rs->fMaxR*rs->fMaxR)
	  {
	    p[0] = (*i)->V.x; p[1] = (*i)->V.y; p[2] = (*i)->V.z;
	    glVertex3f(p[0]-d, p[1], p[2]); glVertex3f(p[0]+d, p[1], p[2]);
	    glVertex3f(p[0], p[1]-d, p[2]); glVertex3f(p[0], p[1]+d, p[2]);
	    glVertex3f(p[0], p[1], p[2]-d); glVertex3f(p[0], p[1], p[2]+d);
	  }
	}
      }
      glEnd();
    } // end render corsses
    glPopAttrib();
  } //if PM not empty
}
<commit_msg>Fix for checking boundaries of path-marks.<commit_after>// $Header$

#include "TrackGL.h"
#include <Reve/Track.h>

#include <TGLDrawFlags.h>

#ifdef WIN32
#include "Windows4root.h"
#endif
#include <GL/gl.h>
#include <GL/glu.h>

using namespace Reve;

//______________________________________________________________________
// TrackGL
//

ClassImp(TrackGL)

TrackGL::TrackGL() : LineGL()
{
  // fCached = false; // Disable display list.
}

TrackGL::~TrackGL()
{}

/**************************************************************************/

Bool_t TrackGL::SetModel(TObject* obj)
{
  if(LineGL::SetModel(obj) == kFALSE) return kFALSE;
  if(SetModelCheckClass(obj, Track::Class())) {
    fTrack = dynamic_cast<Track*>(obj);
    return kTRUE;
  }
  return kFALSE;
}
/**************************************************************************/

void TrackGL::ProcessSelection(UInt_t* ptr, TGLViewer*, TGLScene*)
{
  // Processes secondary selection from TGLViewer.
  // Calls TPointSet3D::PointSelected(Int_t) with index of selected
  // point as an argument.

  Int_t n = ptr[0];
  printf("TrackGL::ProcessSelection %d names on the stack (z1=%g, z2=%g).\n",
	 n, Float_t(ptr[1])/0x7fffffff, Float_t(ptr[2])/0x7fffffff);
  ptr += 3;
  printf("  Names: ");
  for (Int_t j=0; j<n; ++j, ++ptr) printf ("%d ", *ptr);
  printf("\n");

  ((Track*)fM)->CtrlClicked((Track*)fM);
}

/**************************************************************************/
void TrackGL::DirectDraw(const TGLDrawFlags & flags) const
{
  // Render line and path marks

  LineGL::DirectDraw(flags);

  if ( ! fTrack->fPathMarks.empty()){

    TrackRnrStyle* rs = fTrack->GetRnrStyle();
    Int_t  style = rs->fPMStyle;

    UChar_t color[4];
    ColorFromIdx(rs->fPMColor, color);
    glColor4ubv(color);

    glPushAttrib(GL_POINT_BIT | GL_LINE_BIT | GL_ENABLE_BIT);
    glDisable(GL_LIGHTING);

    Int_t ms = rs->fPMStyle;
    // points
    if (ms != 2 && ms != 3 && ms != 5 && ms != 28)
    {
      Float_t size = 5*rs->fPMSize;
      if (style == 4 || style == 20 || style == 24)
      {
	if (style == 4 || style == 24)
	  glEnable(GL_BLEND);
	glEnable(GL_POINT_SMOOTH);
      }
      else
      {
	glDisable(GL_POINT_SMOOTH);
	if      (style == 1) size = 1;
	else if (style == 6) size = 2;
	else if (style == 7) size = 3;
      }
      glPointSize(size);

      glBegin(GL_POINTS);
      Bool_t accept;
      std::vector<PathMark*>& pm = fTrack->fPathMarks;
      for(std::vector<PathMark*>::iterator i=pm.begin(); i!=pm.end(); ++i)
      {
	accept = kFALSE;
	switch((*i)->type)
	{
	  case(PathMark::Daughter):
	    if(rs->fRnrDaughters) accept = kTRUE;
	    break;
	  case(PathMark::Reference):
	    if(rs->fRnrReferences) accept = kTRUE;
	    break;
	  case(PathMark::Decay):
	    if(rs->fRnrDecay) accept = kTRUE;
	    break;
	}
	if(accept)
	{
	  if((TMath::Abs((*i)->V.z) < rs->fMaxZ) && ((*i)->V.Perp() < rs->fMaxR))
	    glVertex3f((*i)->V.x, (*i)->V.y,(*i)->V.z);
	}
      }
      glEnd();
    } // end render points
    else
    {
      // crosses
      if ( style== 28)
      {
	glEnable(GL_BLEND);
	glEnable(GL_LINE_SMOOTH);
	glLineWidth(2);
      }
      else
      {
	glDisable(GL_LINE_SMOOTH);
      }

      glBegin(GL_LINES);
      Bool_t accept;
      Float_t d = 2* rs->fPMSize;
      Float_t p[3];
      std::vector<PathMark*>& pm = fTrack->fPathMarks;
      for(std::vector<PathMark*>::iterator i=pm.begin(); i!=pm.end(); ++i)
      {
	accept = kFALSE;
	switch((*i)->type)
	{
	  case(PathMark::Daughter):
	    if(rs->fRnrDaughters) accept = kTRUE;
	    break;
	  case(PathMark::Reference):
	    if(rs->fRnrReferences) accept = kTRUE;
	    break;
	  case(PathMark::Decay):
	    if(rs->fRnrDecay) accept = kTRUE;
	    break;
	}
	if(accept)
	{
	  if((TMath::Abs((*i)->V.z) < rs->fMaxZ) && ((*i)->V.Perp() < rs->fMaxR))
	  {
	    p[0] = (*i)->V.x; p[1] = (*i)->V.y; p[2] = (*i)->V.z;
	    glVertex3f(p[0]-d, p[1], p[2]); glVertex3f(p[0]+d, p[1], p[2]);
	    glVertex3f(p[0], p[1]-d, p[2]); glVertex3f(p[0], p[1]+d, p[2]);
	    glVertex3f(p[0], p[1], p[2]-d); glVertex3f(p[0], p[1], p[2]+d);
	  }
	}
      }
      glEnd();
    } // end render corsses
    glPopAttrib();
  } //if PM not empty
}
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "boundary_info.h"
#include "elem.h"
#include "libmesh_logging.h"
#include "parallel_mesh.h"
#include "parallel.h"

// ------------------------------------------------------------
// ParallelMesh class member functions
ParallelMesh::ParallelMesh (unsigned int d) :
  UnstructuredMesh (d)
{
}

ParallelMesh::~ParallelMesh ()
{
  this->clear();  // Free nodes and elements
}

// This might be specialized later, but right now it's just here to
// make sure the compiler doesn't give us a default (non-deep) copy
// constructor instead.
ParallelMesh::ParallelMesh (const ParallelMesh &other_mesh) :
  UnstructuredMesh (other_mesh)
{
  this->copy_nodes_and_elements(other_mesh);
}

ParallelMesh::ParallelMesh (const UnstructuredMesh &other_mesh) :
  UnstructuredMesh (other_mesh)
{
  this->copy_nodes_and_elements(other_mesh);
}

const Point& ParallelMesh::point (const unsigned int i) const
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return (*_nodes[i]);
}

const Node& ParallelMesh::node (const unsigned int i) const
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return (*_nodes[i]);
}

Node& ParallelMesh::node (const unsigned int i)
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return (*_nodes[i]);
}

const Node* ParallelMesh::node_ptr (const unsigned int i) const
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return _nodes[i];
}

Node* & ParallelMesh::node_ptr (const unsigned int i)
{
  assert (i < this->max_node_id());

  return _nodes[i];
}

Elem* ParallelMesh::elem (const unsigned int i) const
{
  assert (i < this->max_elem_id());
  assert (_elements[i] != NULL);

  return _elements[i];
}

Elem* ParallelMesh::add_elem (Elem* e)
{
  if (e != NULL)
    e->set_id (this->max_elem_id());

  _elements[this->max_elem_id()] = e;

  return e;
}

Elem* ParallelMesh::insert_elem (Elem* e)
{
  if (_elements[e->id()])
    this->delete_elem(_elements[e->id()]);

  _elements[e->id()] = e;

  return e;
}

void ParallelMesh::delete_elem(Elem* e)
{
  assert (e != NULL);

  // Delete the element from the BoundaryInfo object
  this->boundary_info->remove(e);

  // But not yet from the container; we might invalidate
  // an iterator that way!

  //_elements.erase(e->id());

  // Instead, we set it to NULL for now

  _elements[e->id()] = NULL;

  // delete the element
  delete e;
}

Node* ParallelMesh::add_point (const Point& p)
{
  Node* n = Node::build(p, this->max_node_id()).release();
  _nodes[this->max_node_id()] = n;

  return n;
}

void ParallelMesh::delete_node(Node* n)
{
  assert (n != NULL);
  assert (n->id() < this->max_node_id());

  // Delete the node from the BoundaryInfo object
  this->boundary_info->remove(n);

  // And from the container
  _nodes.erase(n->id());

  // delete the node
  delete n;
}

void ParallelMesh::clear ()
{
  // Call parent clear function
  MeshBase::clear();

  // Clear our elements and nodes
  {
    elem_iterator_imp        it = _elements.begin();
    const elem_iterator_imp end = _elements.end();

    // There is no need to remove the elements from
    // the BoundaryInfo data structure since we
    // already cleared it.
    for (; it != end; ++it)
      delete *it;

    _elements.clear();
  }

  // clear the nodes data structure
  {
    node_iterator_imp it  = _nodes.begin();
    node_iterator_imp end = _nodes.end();

    // There is no need to remove the nodes from
    // the BoundaryInfo data structure since we
    // already cleared it.
    for (; it != end; ++it)
      delete *it;

    _nodes.clear();
  }
}

template <typename T>
void ParallelMesh::renumber_dof_objects (mapvector<T*> &objects)
{
  typedef typename mapvector<T*>::veclike_iterator object_iterator;

  // In parallel we may not know what objects other processors have.
  // Start by figuring out how many
  unsigned int objects_on_me = 0;
  unsigned int unpartitioned_objects = 0;

  object_iterator it  = objects.begin();
  object_iterator end = objects.end();

  for (; it != end;)
    {
      T *obj = *it;

      // Remove any NULL container entries while we're here,
      // being careful not to invalidate our iterator
      if (!*it)
        objects.erase(it++);
      else
        {
          unsigned int obj_procid = obj->processor_id();
          if (obj_procid == libMesh::processor_id())
            objects_on_me++;
          else if (obj_procid == DofObject::invalid_processor_id)
            unpartitioned_objects++;
          ++it;
        }
    }

  std::vector<unsigned int> objects_on_proc(libMesh::n_processors(), 0);
  Parallel::allgather(objects_on_me, objects_on_proc);

#ifdef DEBUG
  unsigned int global_unpartitioned_objects = unpartitioned_objects;
  Parallel::max(global_unpartitioned_objects);
  assert(global_unpartitioned_objects == unpartitioned_objects);
#endif

  // We'll renumber objects in blocks by processor id
  std::vector<unsigned int> first_object_on_proc(libMesh::n_processors());
  for (unsigned int i=1; i != libMesh::n_processors(); ++i)
    first_object_on_proc[i] = first_object_on_proc[i-1] +
                              objects_on_proc[i-1];
  unsigned int next_id = first_object_on_proc[libMesh::processor_id()];

  // First set new local object ids and build request sets
  // for non-local object ids

  // Request sets to send to each processor
  std::vector<std::vector<unsigned int> >
    requested_ids(libMesh::n_processors());

  // We know how many objects live on each processor, so reseve() space for
  // each.
  for (unsigned int p=0; p != libMesh::n_processors(); ++p)
    if (p != libMesh::processor_id())
      requested_ids[p].reserve(objects_on_proc[p]);

  end = objects.end();
  for (it = objects.begin(); it != end; ++it)
    {
      T *obj = *it;
      if (obj->processor_id() == libMesh::processor_id())
        obj->set_id(next_id++);
      else if (obj->processor_id() != DofObject::invalid_processor_id)
        requested_ids[obj->processor_id()].push_back(obj->id());
    }

  // Next set ghost object ids from other processors
  if (libMesh::n_processors() > 1)
    {
      for (unsigned int p=1; p != libMesh::n_processors(); ++p)
        {
          // Trade my requests with processor procup and procdown
          unsigned int procup = (libMesh::processor_id() + p) %
                                 libMesh::n_processors();
          unsigned int procdown = (libMesh::n_processors() +
                                   libMesh::processor_id() - p) %
                                   libMesh::n_processors();
          std::vector<unsigned int> request_to_fill;
          Parallel::send_receive(procup, requested_ids[procup],
                                 procdown, request_to_fill);

          // Fill those requests
          std::vector<unsigned int> new_ids(request_to_fill.size());
          for (unsigned int i=0; i != request_to_fill.size(); ++i)
            {
              assert(objects[request_to_fill[i]]);
              assert(objects[request_to_fill[i]]->processor_id()
                     == libMesh::processor_id());
              new_ids[i] = objects[request_to_fill[i]]->id();
              assert(new_ids[i] >=
                     first_object_on_proc[libMesh::processor_id()]);
              assert(new_ids[i] <
                     first_object_on_proc[libMesh::processor_id()] +
                     objects_on_proc[libMesh::processor_id()]);
            }

          // Trade back the results
          std::vector<unsigned int> filled_request;
          Parallel::send_receive(procdown, new_ids,
                                 procup, filled_request);

          // And copy the id changes we've now been informed of
          for (unsigned int i=0; i != filled_request.size(); ++i)
            {
              assert (objects[requested_ids[procup][i]]->processor_id()
                      == procup);
              assert(filled_request[i] >=
                     first_object_on_proc[procup]);
              assert(filled_request[i] <
                     first_object_on_proc[procup] +
                     objects_on_proc[procup]);
              objects[requested_ids[procup][i]]->set_id(filled_request[i]);
            }
        }
    }

  // Next set unpartitioned object ids
  next_id = 0;
  for (unsigned int i=0; i != libMesh::n_processors(); ++i)
    next_id += objects_on_proc[i];
  for (it = objects.begin(); it != end; ++it)
    {
      T *obj = *it;
      if (obj->processor_id() == DofObject::invalid_processor_id)
        obj->set_id(next_id++);
    }

  // Finally shuffle around objects so that container indices
  // match ids
  end = objects.end();
  for (it = objects.begin(); it != end;)
    {
      T *obj = *it;
      if (obj) // don't try shuffling already-NULL entries
        {
          T *next = objects[obj->id()];
          // If we have to move this object
          if (next != obj)
            {
              // NULL out its original position for now
              // (our shuffling may put another object there shortly)
              *it = NULL;

              // There may already be another object with this id that
              // needs to be moved itself
              while (next)
                {
                  // We shouldn't be trying to give two objects the
                  // same id
                  assert (next->id() != obj->id());
                  objects[obj->id()] = obj;
                  obj = next;
                  next = objects[obj->id()];
                }
              objects[obj->id()] = obj;
            }
        }
      // Remove any container entries that were left as NULL,
      // being careful not to invalidate our iterator
      if (!*it)
        objects.erase(it++);
      else
        ++it;
    }
}

void ParallelMesh::renumber_nodes_and_elements ()
{
  START_LOG("renumber_nodes_and_elem()", "Mesh");

  std::set<unsigned int> used_nodes;

  // flag the nodes we need
  {
    element_iterator  it = elements_begin();
    element_iterator end = elements_end();

    for (; it != end; ++it)
      {
        Elem *elem = *it;

        for (unsigned int n=0; n != elem->n_nodes(); ++n)
          used_nodes.insert(elem->node(n));
      }
  }

  // Nodes not connected to any local elements are deleted
  {
    node_iterator_imp  it = _nodes.begin();
    node_iterator_imp end = _nodes.end();

    for (; it != end;)
      {
	Node *node = *it;
        if (used_nodes.find(node->id()) == used_nodes.end())
          {
	    // remove any boundary information associated with
	    // this node
	    this->boundary_info->remove (node);

	    // delete the node
	    delete node;

            _nodes.erase(it++);
	  }
        else
          ++it;
      }
  }

  // Finally renumber all the elements
  this->renumber_dof_objects (_elements);

  // and all the remaining nodes
  this->renumber_dof_objects (_nodes);

  STOP_LOG("renumber_nodes_and_elem()", "Mesh");
}

void ParallelMesh::delete_nonlocal_elements()
{
  std::vector<bool> local_nodes(this->max_node_id(), false);
  std::vector<bool> semilocal_elems(this->max_elem_id(), false);

  const_element_iterator l_elem_it = this->local_elements_begin(),
                         l_end     = this->local_elements_end();
  for (; l_elem_it != l_end; ++l_elem_it)
    {
      const Elem *elem = *l_elem_it;
      for (unsigned int n=0; n != elem->n_nodes(); ++n)
        local_nodes[elem->node(n)] = true;
    }

  element_iterator nl_elem_it = this->not_local_elements_begin(),
                   nl_end     = this->not_local_elements_end();
  for (; nl_elem_it != nl_end; ++nl_elem_it)
    {
      Elem *elem = *nl_elem_it;
      for (unsigned int n=0; n != elem->n_nodes(); ++n)
        if (local_nodes[elem->node(n)])
          {
            semilocal_elems[elem->id()] = true;
            break;
          }
      if (!semilocal_elems[elem->id()])
        {
          // delete_elem doesn't currently invalidate element
          // iterators... that had better not change
          this->delete_elem(elem);
        }
    }
//  We eventually want to compact the _nodes and _elems vectors
//  But not do a repartition or anything
//  do not this->prepare_for_use();
}

void ParallelMesh::restore_nonlocal_elements()
{
  // Someday...
  error();
}
<commit_msg>reserve() space for efficiency since the information we need to do that is freely available.<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "boundary_info.h"
#include "elem.h"
#include "libmesh_logging.h"
#include "parallel_mesh.h"
#include "parallel.h"

// ------------------------------------------------------------
// ParallelMesh class member functions
ParallelMesh::ParallelMesh (unsigned int d) :
  UnstructuredMesh (d)
{
}

ParallelMesh::~ParallelMesh ()
{
  this->clear();  // Free nodes and elements
}

// This might be specialized later, but right now it's just here to
// make sure the compiler doesn't give us a default (non-deep) copy
// constructor instead.
ParallelMesh::ParallelMesh (const ParallelMesh &other_mesh) :
  UnstructuredMesh (other_mesh)
{
  this->copy_nodes_and_elements(other_mesh);
}

ParallelMesh::ParallelMesh (const UnstructuredMesh &other_mesh) :
  UnstructuredMesh (other_mesh)
{
  this->copy_nodes_and_elements(other_mesh);
}

const Point& ParallelMesh::point (const unsigned int i) const
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return (*_nodes[i]);
}

const Node& ParallelMesh::node (const unsigned int i) const
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return (*_nodes[i]);
}

Node& ParallelMesh::node (const unsigned int i)
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return (*_nodes[i]);
}

const Node* ParallelMesh::node_ptr (const unsigned int i) const
{
  assert (i < this->max_node_id());
  assert (_nodes[i] != NULL);
  assert (_nodes[i]->id() != Node::invalid_id);

  return _nodes[i];
}

Node* & ParallelMesh::node_ptr (const unsigned int i)
{
  assert (i < this->max_node_id());

  return _nodes[i];
}

Elem* ParallelMesh::elem (const unsigned int i) const
{
  assert (i < this->max_elem_id());
  assert (_elements[i] != NULL);

  return _elements[i];
}

Elem* ParallelMesh::add_elem (Elem* e)
{
  if (e != NULL)
    e->set_id (this->max_elem_id());

  _elements[this->max_elem_id()] = e;

  return e;
}

Elem* ParallelMesh::insert_elem (Elem* e)
{
  if (_elements[e->id()])
    this->delete_elem(_elements[e->id()]);

  _elements[e->id()] = e;

  return e;
}

void ParallelMesh::delete_elem(Elem* e)
{
  assert (e != NULL);

  // Delete the element from the BoundaryInfo object
  this->boundary_info->remove(e);

  // But not yet from the container; we might invalidate
  // an iterator that way!

  //_elements.erase(e->id());

  // Instead, we set it to NULL for now

  _elements[e->id()] = NULL;

  // delete the element
  delete e;
}

Node* ParallelMesh::add_point (const Point& p)
{
  Node* n = Node::build(p, this->max_node_id()).release();
  _nodes[this->max_node_id()] = n;

  return n;
}

void ParallelMesh::delete_node(Node* n)
{
  assert (n != NULL);
  assert (n->id() < this->max_node_id());

  // Delete the node from the BoundaryInfo object
  this->boundary_info->remove(n);

  // And from the container
  _nodes.erase(n->id());

  // delete the node
  delete n;
}

void ParallelMesh::clear ()
{
  // Call parent clear function
  MeshBase::clear();

  // Clear our elements and nodes
  {
    elem_iterator_imp        it = _elements.begin();
    const elem_iterator_imp end = _elements.end();

    // There is no need to remove the elements from
    // the BoundaryInfo data structure since we
    // already cleared it.
    for (; it != end; ++it)
      delete *it;

    _elements.clear();
  }

  // clear the nodes data structure
  {
    node_iterator_imp it  = _nodes.begin();
    node_iterator_imp end = _nodes.end();

    // There is no need to remove the nodes from
    // the BoundaryInfo data structure since we
    // already cleared it.
    for (; it != end; ++it)
      delete *it;

    _nodes.clear();
  }
}

template <typename T>
void ParallelMesh::renumber_dof_objects (mapvector<T*> &objects)
{
  typedef typename mapvector<T*>::veclike_iterator object_iterator;

  // In parallel we may not know what objects other processors have.
  // Start by figuring out how many
  unsigned int objects_on_me = 0;
  unsigned int unpartitioned_objects = 0;

  object_iterator it  = objects.begin();
  object_iterator end = objects.end();

  for (; it != end;)
    {
      T *obj = *it;

      // Remove any NULL container entries while we're here,
      // being careful not to invalidate our iterator
      if (!*it)
        objects.erase(it++);
      else
        {
          unsigned int obj_procid = obj->processor_id();
          if (obj_procid == libMesh::processor_id())
            objects_on_me++;
          else if (obj_procid == DofObject::invalid_processor_id)
            unpartitioned_objects++;
          ++it;
        }
    }

  std::vector<unsigned int> objects_on_proc(libMesh::n_processors(), 0);
  Parallel::allgather(objects_on_me, objects_on_proc);

#ifdef DEBUG
  unsigned int global_unpartitioned_objects = unpartitioned_objects;
  Parallel::max(global_unpartitioned_objects);
  assert(global_unpartitioned_objects == unpartitioned_objects);
#endif

  // We'll renumber objects in blocks by processor id
  std::vector<unsigned int> first_object_on_proc(libMesh::n_processors());
  for (unsigned int i=1; i != libMesh::n_processors(); ++i)
    first_object_on_proc[i] = first_object_on_proc[i-1] +
                              objects_on_proc[i-1];
  unsigned int next_id = first_object_on_proc[libMesh::processor_id()];

  // First set new local object ids and build request sets
  // for non-local object ids

  // Request sets to send to each processor
  std::vector<std::vector<unsigned int> >
    requested_ids(libMesh::n_processors());

  // We know how many objects live on each processor, so reseve() space for
  // each.
  for (unsigned int p=0; p != libMesh::n_processors(); ++p)
    if (p != libMesh::processor_id())
      requested_ids[p].reserve(objects_on_proc[p]);

  end = objects.end();
  for (it = objects.begin(); it != end; ++it)
    {
      T *obj = *it;
      if (obj->processor_id() == libMesh::processor_id())
        obj->set_id(next_id++);
      else if (obj->processor_id() != DofObject::invalid_processor_id)
        requested_ids[obj->processor_id()].push_back(obj->id());
    }

  // Next set ghost object ids from other processors
  if (libMesh::n_processors() > 1)
    {
      for (unsigned int p=1; p != libMesh::n_processors(); ++p)
        {
          // Trade my requests with processor procup and procdown
          unsigned int procup = (libMesh::processor_id() + p) %
                                 libMesh::n_processors();
          unsigned int procdown = (libMesh::n_processors() +
                                   libMesh::processor_id() - p) %
                                   libMesh::n_processors();
          std::vector<unsigned int> request_to_fill;
          Parallel::send_receive(procup, requested_ids[procup],
                                 procdown, request_to_fill);

          // Fill those requests
          std::vector<unsigned int> new_ids(request_to_fill.size());
          for (unsigned int i=0; i != request_to_fill.size(); ++i)
            {
              assert(objects[request_to_fill[i]]);
              assert(objects[request_to_fill[i]]->processor_id()
                     == libMesh::processor_id());
              new_ids[i] = objects[request_to_fill[i]]->id();
              assert(new_ids[i] >=
                     first_object_on_proc[libMesh::processor_id()]);
              assert(new_ids[i] <
                     first_object_on_proc[libMesh::processor_id()] +
                     objects_on_proc[libMesh::processor_id()]);
            }

          // Trade back the results
          std::vector<unsigned int> filled_request;
          Parallel::send_receive(procdown, new_ids,
                                 procup, filled_request);

          // And copy the id changes we've now been informed of
          for (unsigned int i=0; i != filled_request.size(); ++i)
            {
              assert (objects[requested_ids[procup][i]]->processor_id()
                      == procup);
              assert(filled_request[i] >=
                     first_object_on_proc[procup]);
              assert(filled_request[i] <
                     first_object_on_proc[procup] +
                     objects_on_proc[procup]);
              objects[requested_ids[procup][i]]->set_id(filled_request[i]);
            }
        }
    }

  // Next set unpartitioned object ids
  next_id = 0;
  for (unsigned int i=0; i != libMesh::n_processors(); ++i)
    next_id += objects_on_proc[i];
  for (it = objects.begin(); it != end; ++it)
    {
      T *obj = *it;
      if (obj->processor_id() == DofObject::invalid_processor_id)
        obj->set_id(next_id++);
    }

  // Finally shuffle around objects so that container indices
  // match ids
  end = objects.end();
  for (it = objects.begin(); it != end;)
    {
      T *obj = *it;
      if (obj) // don't try shuffling already-NULL entries
        {
          T *next = objects[obj->id()];
          // If we have to move this object
          if (next != obj)
            {
              // NULL out its original position for now
              // (our shuffling may put another object there shortly)
              *it = NULL;

              // There may already be another object with this id that
              // needs to be moved itself
              while (next)
                {
                  // We shouldn't be trying to give two objects the
                  // same id
                  assert (next->id() != obj->id());
                  objects[obj->id()] = obj;
                  obj = next;
                  next = objects[obj->id()];
                }
              objects[obj->id()] = obj;
            }
        }
      // Remove any container entries that were left as NULL,
      // being careful not to invalidate our iterator
      if (!*it)
        objects.erase(it++);
      else
        ++it;
    }
}

void ParallelMesh::renumber_nodes_and_elements ()
{
  START_LOG("renumber_nodes_and_elem()", "Mesh");

  std::set<unsigned int> used_nodes;

  // flag the nodes we need
  {
    element_iterator  it = elements_begin();
    element_iterator end = elements_end();

    for (; it != end; ++it)
      {
        Elem *elem = *it;

        for (unsigned int n=0; n != elem->n_nodes(); ++n)
          used_nodes.insert(elem->node(n));
      }
  }

  // Nodes not connected to any local elements are deleted
  {
    node_iterator_imp  it = _nodes.begin();
    node_iterator_imp end = _nodes.end();

    for (; it != end;)
      {
	Node *node = *it;
        if (!used_nodes.count(node->id()))
          {
	    // remove any boundary information associated with
	    // this node
	    this->boundary_info->remove (node);

	    // delete the node
	    delete node;

            _nodes.erase(it++);
	  }
        else
          ++it;
      }
  }

  // Finally renumber all the elements
  this->renumber_dof_objects (_elements);

  // and all the remaining nodes
  this->renumber_dof_objects (_nodes);

  STOP_LOG("renumber_nodes_and_elem()", "Mesh");
}

void ParallelMesh::delete_nonlocal_elements()
{
  std::vector<bool> local_nodes(this->max_node_id(), false);
  std::vector<bool> semilocal_elems(this->max_elem_id(), false);

  const_element_iterator l_elem_it = this->local_elements_begin(),
                         l_end     = this->local_elements_end();
  for (; l_elem_it != l_end; ++l_elem_it)
    {
      const Elem *elem = *l_elem_it;
      for (unsigned int n=0; n != elem->n_nodes(); ++n)
        local_nodes[elem->node(n)] = true;
    }

  element_iterator nl_elem_it = this->not_local_elements_begin(),
                   nl_end     = this->not_local_elements_end();
  for (; nl_elem_it != nl_end; ++nl_elem_it)
    {
      Elem *elem = *nl_elem_it;
      for (unsigned int n=0; n != elem->n_nodes(); ++n)
        if (local_nodes[elem->node(n)])
          {
            semilocal_elems[elem->id()] = true;
            break;
          }
      if (!semilocal_elems[elem->id()])
        {
          // delete_elem doesn't currently invalidate element
          // iterators... that had better not change
          this->delete_elem(elem);
        }
    }
//  We eventually want to compact the _nodes and _elems vectors
//  But not do a repartition or anything
//  do not this->prepare_for_use();
}

void ParallelMesh::restore_nonlocal_elements()
{
  // Someday...
  error();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: LockSequence.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: rt $ $Date: 2008-02-19 12:34:15 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"

#include <string.h>

#ifndef NE_XML_H
#include <ne_xml.h>
#endif

#ifndef _LOCKSEQUENCE_HXX_
#include "LockSequence.hxx"
#endif

using namespace webdav_ucp;
using namespace com::sun::star;

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

struct LockSequenceParseContext
{
    ucb::Lock * pLock;
    bool hasLockScope;
    bool hasLockType;
    bool hasDepth;
    bool hasHREF;
    bool hasTimeout;

    LockSequenceParseContext()
    : pLock( 0 ), hasLockScope( false ), hasLockType( false ),
      hasDepth( false ), hasHREF( false ), hasTimeout( false ) {}

    ~LockSequenceParseContext() { delete pLock; }
};

#define STATE_TOP (1)

#define STATE_ACTIVELOCK    (STATE_TOP)
#define STATE_LOCKSCOPE     (STATE_TOP + 1)
#define STATE_LOCKTYPE      (STATE_TOP + 2)
#define STATE_DEPTH         (STATE_TOP + 3)
#define STATE_OWNER         (STATE_TOP + 4)
#define STATE_TIMEOUT       (STATE_TOP + 5)
#define STATE_LOCKTOKEN     (STATE_TOP + 6)
#define STATE_EXCLUSIVE     (STATE_TOP + 7)
#define STATE_SHARED        (STATE_TOP + 8)
#define STATE_WRITE         (STATE_TOP + 9)
#define STATE_HREF          (STATE_TOP + 10)

//////////////////////////////////////////////////////////////////////////
extern "C" int LockSequence_startelement_callback(
    void *,
    int parent,
    const char *nspace,
    const char *name,
    const char ** )
{
    if ( ( name != 0 ) &&
         ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) )
    {
        switch ( parent )
        {
            case NE_XML_STATEROOT:
                if ( strcmp( name, "activelock" ) == 0 )
                    return STATE_ACTIVELOCK;
                break;

            case STATE_ACTIVELOCK:
                if ( strcmp( name, "lockscope" ) == 0 )
                    return STATE_LOCKSCOPE;
                else if ( strcmp( name, "locktype" ) == 0 )
                    return STATE_LOCKTYPE;
                else if ( strcmp( name, "depth" ) == 0 )
                    return STATE_DEPTH;
                else if ( strcmp( name, "owner" ) == 0 )
                    return STATE_OWNER;
                else if ( strcmp( name, "timeout" ) == 0 )
                    return STATE_TIMEOUT;
                else if ( strcmp( name, "locktoken" ) == 0 )
                    return STATE_LOCKTOKEN;
                break;

            case STATE_LOCKSCOPE:
                if ( strcmp( name, "exclusive" ) == 0 )
                    return STATE_EXCLUSIVE;
                else if ( strcmp( name, "shared" ) == 0 )
                    return STATE_SHARED;
                break;

            case STATE_LOCKTYPE:
                if ( strcmp( name, "write" ) == 0 )
                    return STATE_WRITE;
                break;

            case STATE_LOCKTOKEN:
                if ( strcmp( name, "href" ) == 0 )
                    return STATE_HREF;
                break;

            case STATE_OWNER:
                // owner elem contains ANY. Accept anything; no state change.
                return STATE_OWNER;
        }
    }
    return NE_XML_DECLINE;
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LockSequence_chardata_callback(
    void *userdata,
    int state,
    const char *buf,
    size_t len )
{
    LockSequenceParseContext * pCtx
                    = static_cast< LockSequenceParseContext * >( userdata );
    if ( !pCtx->pLock )
        pCtx->pLock = new ucb::Lock;

    switch ( state )
    {
        case STATE_DEPTH:
            if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "0", 1 ) == 0 )
            {
                pCtx->pLock->Depth = ucb::LockDepth_ZERO;
                pCtx->hasDepth = true;
            }
            else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "1", 1 ) == 0 )
            {
                pCtx->pLock->Depth = ucb::LockDepth_ONE;
                pCtx->hasDepth = true;
            }
            else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "infinity", 8 ) == 0 )
            {
                pCtx->pLock->Depth = ucb::LockDepth_INFINITY;
                pCtx->hasDepth = true;
            }
            else
                OSL_ENSURE( sal_False,
                            "LockSequence_chardata_callback - Unknown depth!" );
            break;

        case STATE_OWNER:
        {
            // collect raw XML data... (owner contains ANY)
            rtl::OUString aValue;
            pCtx->pLock->Owner >>= aValue;
            aValue += rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
            pCtx->pLock->Owner <<= aValue;
            break;
        }

        case STATE_TIMEOUT:
            //
            //  RFC2518, RFC2616:
            //
            //  TimeType = ("Second-" DAVTimeOutVal | "Infinite" | Other)
            //  DAVTimeOutVal = 1*digit
            //  Other = "Extend" field-value
            //  field-value = *( field-content | LWS )
            //  field-content = <the OCTETs making up the field-value
            //                  and consisting of either *TEXT or combinations
            //                  of token, separators, and quoted-string>

            if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "Infinite", 8 ) == 0 )
            {
                pCtx->pLock->Timeout = sal_Int64( -1 );
                pCtx->hasTimeout = true;
            }
            else if ( rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
                                            buf, len, "Second-", 7, 7 ) == 0 )
            {
                pCtx->pLock->Timeout
                    = rtl::OString( buf + 7, len - 7 ).toInt64();
                pCtx->hasTimeout = true;
            }
//          else if ( rtl_str_shortenedCompareIgnoreCase_WithLength(
//                                          buf, len, "Extend", 6, 6 ) == 0 )
//          {
//              @@@
//          }
            else
            {
                pCtx->pLock->Timeout = sal_Int64( -1 );
                pCtx->hasTimeout = true;
                OSL_ENSURE( sal_False,
                        "LockSequence_chardata_callback - Unknown timeout!" );
            }
            break;

        case STATE_HREF:
        {
            // collect hrefs.
            sal_Int32 nPos = pCtx->pLock->LockTokens.getLength();
            pCtx->pLock->LockTokens.realloc( nPos + 1 );
            pCtx->pLock->LockTokens[ nPos ]
                = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
            pCtx->hasHREF = true;
            break;
        }

    }
    return 0; // zero to continue, non-zero to abort parsing
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LockSequence_endelement_callback(
    void *userdata,
    int state,
    const char *,
    const char * )
{
    LockSequenceParseContext * pCtx
                    = static_cast< LockSequenceParseContext * >( userdata );
    if ( !pCtx->pLock )
        pCtx->pLock = new ucb::Lock;

    switch ( state )
    {
        case STATE_EXCLUSIVE:
            pCtx->pLock->Scope = ucb::LockScope_EXCLUSIVE;
            pCtx->hasLockScope = true;
            break;

        case STATE_SHARED:
            pCtx->pLock->Scope = ucb::LockScope_SHARED;
            pCtx->hasLockScope = true;
            break;

        case STATE_WRITE:
            pCtx->pLock->Type = ucb::LockType_WRITE;
            pCtx->hasLockType = true;
            break;

        case STATE_DEPTH:
            if ( !pCtx->hasDepth )
                return 1; // abort
            break;

        case STATE_HREF:
            if ( !pCtx->hasHREF )
                return 1; // abort
            break;

        case STATE_TIMEOUT:
            if ( !pCtx->hasTimeout )
                return 1; // abort
            break;

        case STATE_LOCKSCOPE:
            if ( !pCtx->hasLockScope )
                return 1; // abort
            break;

        case STATE_LOCKTYPE:
            if ( !pCtx->hasLockType )
                return 1; // abort
            break;

        case STATE_ACTIVELOCK:
            if ( !pCtx->hasLockType || !pCtx->hasLockType || !pCtx->hasDepth )
                return 1; // abort
            break;

        default:
            break;
    }
    return 0; // zero to continue, non-zero to abort parsing
}

//////////////////////////////////////////////////////////////////////////
// static
bool LockSequence::createFromXML( const rtl::OString & rInData,
                                  uno::Sequence< ucb::Lock > & rOutData )
{
    const sal_Int32 TOKEN_LENGTH = 13; // </activelock>
    bool success = true;

    // rInData may contain multiple <activelock>...</activelock> tags.
    sal_Int32 nCount = 0;
    sal_Int32 nStart = 0;
    sal_Int32 nEnd   = rInData.indexOf( "</activelock>" );
    while ( nEnd > -1 )
    {
        ne_xml_parser * parser = ne_xml_create();
        if ( !parser )
        {
            success = false;
            break;
        }

        LockSequenceParseContext aCtx;
        ne_xml_push_handler( parser,
                             LockSequence_startelement_callback,
                             LockSequence_chardata_callback,
                             LockSequence_endelement_callback,
                             &aCtx );

        ne_xml_parse( parser,
                      rInData.getStr() + nStart,
                      nEnd - nStart + TOKEN_LENGTH );

#if NEON_VERSION >= 0x0250
        success = !ne_xml_failed( parser );
#else
        success = !!ne_xml_valid( parser );
#endif

        ne_xml_destroy( parser );

        if ( !success )
            break;

        if ( aCtx.pLock )
        {
            nCount++;
            if ( nCount > rOutData.getLength() )
                rOutData.realloc( rOutData.getLength() + 1 );

            rOutData[ nCount - 1 ] = *aCtx.pLock;
        }

        nStart = nEnd + TOKEN_LENGTH + 1;
        nEnd   = rInData.indexOf( "</activelock>", nStart );
    }

    return success;
}
<commit_msg>INTEGRATION: CWS changefileheader (1.16.16); FILE MERGED 2008/04/01 16:02:26 thb 1.16.16.3: #i85898# Stripping all external header guards 2008/04/01 12:58:26 thb 1.16.16.2: #i85898# Stripping all external header guards 2008/03/31 15:30:31 rt 1.16.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: LockSequence.cxx,v $
 * $Revision: 1.17 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"

#include <string.h>
#include <ne_xml.h>
#include "LockSequence.hxx"

using namespace webdav_ucp;
using namespace com::sun::star;

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

struct LockSequenceParseContext
{
    ucb::Lock * pLock;
    bool hasLockScope;
    bool hasLockType;
    bool hasDepth;
    bool hasHREF;
    bool hasTimeout;

    LockSequenceParseContext()
    : pLock( 0 ), hasLockScope( false ), hasLockType( false ),
      hasDepth( false ), hasHREF( false ), hasTimeout( false ) {}

    ~LockSequenceParseContext() { delete pLock; }
};

#define STATE_TOP (1)

#define STATE_ACTIVELOCK    (STATE_TOP)
#define STATE_LOCKSCOPE     (STATE_TOP + 1)
#define STATE_LOCKTYPE      (STATE_TOP + 2)
#define STATE_DEPTH         (STATE_TOP + 3)
#define STATE_OWNER         (STATE_TOP + 4)
#define STATE_TIMEOUT       (STATE_TOP + 5)
#define STATE_LOCKTOKEN     (STATE_TOP + 6)
#define STATE_EXCLUSIVE     (STATE_TOP + 7)
#define STATE_SHARED        (STATE_TOP + 8)
#define STATE_WRITE         (STATE_TOP + 9)
#define STATE_HREF          (STATE_TOP + 10)

//////////////////////////////////////////////////////////////////////////
extern "C" int LockSequence_startelement_callback(
    void *,
    int parent,
    const char *nspace,
    const char *name,
    const char ** )
{
    if ( ( name != 0 ) &&
         ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) )
    {
        switch ( parent )
        {
            case NE_XML_STATEROOT:
                if ( strcmp( name, "activelock" ) == 0 )
                    return STATE_ACTIVELOCK;
                break;

            case STATE_ACTIVELOCK:
                if ( strcmp( name, "lockscope" ) == 0 )
                    return STATE_LOCKSCOPE;
                else if ( strcmp( name, "locktype" ) == 0 )
                    return STATE_LOCKTYPE;
                else if ( strcmp( name, "depth" ) == 0 )
                    return STATE_DEPTH;
                else if ( strcmp( name, "owner" ) == 0 )
                    return STATE_OWNER;
                else if ( strcmp( name, "timeout" ) == 0 )
                    return STATE_TIMEOUT;
                else if ( strcmp( name, "locktoken" ) == 0 )
                    return STATE_LOCKTOKEN;
                break;

            case STATE_LOCKSCOPE:
                if ( strcmp( name, "exclusive" ) == 0 )
                    return STATE_EXCLUSIVE;
                else if ( strcmp( name, "shared" ) == 0 )
                    return STATE_SHARED;
                break;

            case STATE_LOCKTYPE:
                if ( strcmp( name, "write" ) == 0 )
                    return STATE_WRITE;
                break;

            case STATE_LOCKTOKEN:
                if ( strcmp( name, "href" ) == 0 )
                    return STATE_HREF;
                break;

            case STATE_OWNER:
                // owner elem contains ANY. Accept anything; no state change.
                return STATE_OWNER;
        }
    }
    return NE_XML_DECLINE;
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LockSequence_chardata_callback(
    void *userdata,
    int state,
    const char *buf,
    size_t len )
{
    LockSequenceParseContext * pCtx
                    = static_cast< LockSequenceParseContext * >( userdata );
    if ( !pCtx->pLock )
        pCtx->pLock = new ucb::Lock;

    switch ( state )
    {
        case STATE_DEPTH:
            if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "0", 1 ) == 0 )
            {
                pCtx->pLock->Depth = ucb::LockDepth_ZERO;
                pCtx->hasDepth = true;
            }
            else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "1", 1 ) == 0 )
            {
                pCtx->pLock->Depth = ucb::LockDepth_ONE;
                pCtx->hasDepth = true;
            }
            else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "infinity", 8 ) == 0 )
            {
                pCtx->pLock->Depth = ucb::LockDepth_INFINITY;
                pCtx->hasDepth = true;
            }
            else
                OSL_ENSURE( sal_False,
                            "LockSequence_chardata_callback - Unknown depth!" );
            break;

        case STATE_OWNER:
        {
            // collect raw XML data... (owner contains ANY)
            rtl::OUString aValue;
            pCtx->pLock->Owner >>= aValue;
            aValue += rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
            pCtx->pLock->Owner <<= aValue;
            break;
        }

        case STATE_TIMEOUT:
            //
            //  RFC2518, RFC2616:
            //
            //  TimeType = ("Second-" DAVTimeOutVal | "Infinite" | Other)
            //  DAVTimeOutVal = 1*digit
            //  Other = "Extend" field-value
            //  field-value = *( field-content | LWS )
            //  field-content = <the OCTETs making up the field-value
            //                  and consisting of either *TEXT or combinations
            //                  of token, separators, and quoted-string>

            if ( rtl_str_compareIgnoreAsciiCase_WithLength(
                    buf, len, "Infinite", 8 ) == 0 )
            {
                pCtx->pLock->Timeout = sal_Int64( -1 );
                pCtx->hasTimeout = true;
            }
            else if ( rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
                                            buf, len, "Second-", 7, 7 ) == 0 )
            {
                pCtx->pLock->Timeout
                    = rtl::OString( buf + 7, len - 7 ).toInt64();
                pCtx->hasTimeout = true;
            }
//          else if ( rtl_str_shortenedCompareIgnoreCase_WithLength(
//                                          buf, len, "Extend", 6, 6 ) == 0 )
//          {
//              @@@
//          }
            else
            {
                pCtx->pLock->Timeout = sal_Int64( -1 );
                pCtx->hasTimeout = true;
                OSL_ENSURE( sal_False,
                        "LockSequence_chardata_callback - Unknown timeout!" );
            }
            break;

        case STATE_HREF:
        {
            // collect hrefs.
            sal_Int32 nPos = pCtx->pLock->LockTokens.getLength();
            pCtx->pLock->LockTokens.realloc( nPos + 1 );
            pCtx->pLock->LockTokens[ nPos ]
                = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
            pCtx->hasHREF = true;
            break;
        }

    }
    return 0; // zero to continue, non-zero to abort parsing
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LockSequence_endelement_callback(
    void *userdata,
    int state,
    const char *,
    const char * )
{
    LockSequenceParseContext * pCtx
                    = static_cast< LockSequenceParseContext * >( userdata );
    if ( !pCtx->pLock )
        pCtx->pLock = new ucb::Lock;

    switch ( state )
    {
        case STATE_EXCLUSIVE:
            pCtx->pLock->Scope = ucb::LockScope_EXCLUSIVE;
            pCtx->hasLockScope = true;
            break;

        case STATE_SHARED:
            pCtx->pLock->Scope = ucb::LockScope_SHARED;
            pCtx->hasLockScope = true;
            break;

        case STATE_WRITE:
            pCtx->pLock->Type = ucb::LockType_WRITE;
            pCtx->hasLockType = true;
            break;

        case STATE_DEPTH:
            if ( !pCtx->hasDepth )
                return 1; // abort
            break;

        case STATE_HREF:
            if ( !pCtx->hasHREF )
                return 1; // abort
            break;

        case STATE_TIMEOUT:
            if ( !pCtx->hasTimeout )
                return 1; // abort
            break;

        case STATE_LOCKSCOPE:
            if ( !pCtx->hasLockScope )
                return 1; // abort
            break;

        case STATE_LOCKTYPE:
            if ( !pCtx->hasLockType )
                return 1; // abort
            break;

        case STATE_ACTIVELOCK:
            if ( !pCtx->hasLockType || !pCtx->hasLockType || !pCtx->hasDepth )
                return 1; // abort
            break;

        default:
            break;
    }
    return 0; // zero to continue, non-zero to abort parsing
}

//////////////////////////////////////////////////////////////////////////
// static
bool LockSequence::createFromXML( const rtl::OString & rInData,
                                  uno::Sequence< ucb::Lock > & rOutData )
{
    const sal_Int32 TOKEN_LENGTH = 13; // </activelock>
    bool success = true;

    // rInData may contain multiple <activelock>...</activelock> tags.
    sal_Int32 nCount = 0;
    sal_Int32 nStart = 0;
    sal_Int32 nEnd   = rInData.indexOf( "</activelock>" );
    while ( nEnd > -1 )
    {
        ne_xml_parser * parser = ne_xml_create();
        if ( !parser )
        {
            success = false;
            break;
        }

        LockSequenceParseContext aCtx;
        ne_xml_push_handler( parser,
                             LockSequence_startelement_callback,
                             LockSequence_chardata_callback,
                             LockSequence_endelement_callback,
                             &aCtx );

        ne_xml_parse( parser,
                      rInData.getStr() + nStart,
                      nEnd - nStart + TOKEN_LENGTH );

#if NEON_VERSION >= 0x0250
        success = !ne_xml_failed( parser );
#else
        success = !!ne_xml_valid( parser );
#endif

        ne_xml_destroy( parser );

        if ( !success )
            break;

        if ( aCtx.pLock )
        {
            nCount++;
            if ( nCount > rOutData.getLength() )
                rOutData.realloc( rOutData.getLength() + 1 );

            rOutData[ nCount - 1 ] = *aCtx.pLock;
        }

        nStart = nEnd + TOKEN_LENGTH + 1;
        nEnd   = rInData.indexOf( "</activelock>", nStart );
    }

    return success;
}
<|endoftext|>