<commit_before>#ifndef MUNCHAR
#define MUNCHAR

#include <cstddef>

namespace Munchar {

  // Unconditional success

  struct Success {
    const char* operator()(const char* b, const char* e) const {
      return b;
    }
  };

  // Unconditional failure

  struct Failure {
    const char* operator()(const char* b, const char* e) const {
      return nullptr;
    }
  };

  // Arbitrary character

  struct Any_Char {
    const char* operator()(const char* b, const char* e) const {
      return b != e ? b+1 : nullptr;
    }
  };

  // Character constant

  class Char {
    const char c_;
  public:
    constexpr Char(const char c) : c_(c) { }
    const char* operator()(const char* b, const char* e) const {
      return b != e && *b == c_ ? b+1 : nullptr;
    }
  };

  constexpr Char operator"" _lit(const char c) {
    return Char { c };
  }

  // String constant

  template<typename Ptr = const char*>
  class Str {
    Ptr s_;
    size_t len_;
  public:
    constexpr Str(Ptr s, size_t len) : s_(s), len_(len) { }
    const char* operator()(const char* b, const char* e) const {
      Ptr s = s_;
      for (size_t i = 0; i < len_; ++i, ++b, ++s) {
        if ((b == e) || (*s_ != *b)) return nullptr;
      }
      return b;
    }
  };

  constexpr Str<> operator"" _lit(const char* c, size_t len) {
    return Str<> { c, len };
  }

  // Character class

  template<typename Ptr = const char*>
  class Char_Class {
    Ptr s_;
    size_t len_;
  public:
    constexpr Char_Class(Ptr s, size_t len) : s_(s), len_(len) { }
    const char* operator()(const char* b, const char* e) const {
      if (b == e) return nullptr;
      Ptr s = s_;
      for (size_t i = 0; i < len_; ++i, ++s) if (*s == *b) return b+1;
      return nullptr;
    }
  };

  constexpr Char_Class<> operator"" _cls(const char* c, size_t len) {
    return Char_Class<> { c, len };
  }

  // Base class for unary combinators

  template<typename M>
  class Unary {
  protected:
    const M m_;
  public:
    constexpr Unary(const M& m) : m_(m) { }
  };

  // Base class for binary combinators

  template<typename L, typename R>
  class Binary {
  protected:
    const L l_;
    const R r_;
  public:
    constexpr Binary(const L& l, const R& r) : l_(l), r_(r) { }
  };

  // Sequencing

  template<typename L, typename R>
  class Sequence : public Binary<L, R> {
  public:
    using Binary<L, R>::Binary;
    const char* operator()(const char* b, const char* e) const {
      return (b = this->l_(b, e)) ? this->r_(b, e) : nullptr;
    }
  };

  template<typename L, typename R>
  constexpr Sequence<L, R> operator^(const L& l, const R& r) {
    return Sequence<L, R> { l, r };
  }

  // Alternation

  template<typename L, typename R>
  class Alternation : public Binary<L, R> {
  public:
    using Binary<L, R>::Binary;
    const char* operator()(const char* b, const char* e) const {
      return (b = this->l_(b, e)) ? b : this->r_(b, e);
    }
  };

  template<typename L, typename R>
  constexpr Alternation<L, R> operator|(const L& l, const R& r) {
    return Alternation<L, R> { l, r };
  }

  // Option

  template<typename M>
  constexpr auto operator~(const M& m)
  -> decltype(m | Success { }) {
    return m | Success { };
  }

  // Repetition

  template<typename M>
  class Zero_Or_More : public Unary<M> {
  public:
    using Unary<M>::Unary;
    const char* operator()(const char* b, const char* e) const {
      for (const char* p = b; (p = this->m_(b, e)); b = p) ;
      return b;
    }
  };

  template<typename M>
  constexpr Zero_Or_More<M> operator*(const M& m) {
    return Zero_Or_More<M> { m };
  }

  template<typename M>
  constexpr auto operator+(const M& m)
  -> decltype(m ^ *m) {
    return m ^ *m;
  }

  // Bounded repetition

  template<typename M>
  class Exactly_N_Times : public Unary<M> {
    size_t n_;
  public:
    constexpr Exactly_N_Times(const M& m, size_t n) : Unary<M> { m }, n_(n) { }
    const char* operator()(const char* b, const char* e) const {
      size_t i;
      for (i = 0; i < n_ && (b = this->m_(b, e)); ++i) ;
      return i == n_ ? b : nullptr;
    }
  };

  template<typename M>
  constexpr Exactly_N_Times<M> operator==(const M& m,  size_t n) {
    return Exactly_N_Times<M> { m, n };
  }

  template<typename M>
  constexpr auto operator>(const M& m,  size_t n)
  -> decltype((m == n) ^ +m) {
    return (m == n) ^ +m;
  }

  template<typename M>
  constexpr auto operator>=(const M& m,  size_t n)
  -> decltype((m == n) ^ *m) {
    return (m == n) ^ *m;
  }

  template<typename M>
  constexpr auto operator<(const M& m,  size_t n)
  -> decltype((m == n-1) | *m) {
    return (m == n-1) | *m;
  }

  template<typename M>
  constexpr auto operator<=(const M& m,  size_t n)
  -> decltype((m == n) | *m) {
    return (m == n) | *m;
  }

  template<typename M>
  constexpr auto between(size_t a, size_t b, const M& m)
  -> decltype((m == a) ^ (m <= b)) {
    return (m == a) ^ (m <= b);
  }

  // Negation

  template<typename M>
  class Negation : Unary<M> {
  public:
    using Unary<M>::Unary;
    const char* operator()(const char* b, const char* e) const {
      return this->m_(b, e) ? nullptr : b;
    }
  };

  template<typename M>
  constexpr Negation<M> operator!(const M& m) {
    return Negation<M> { m };
  }

  // Lookahead

  template<typename M>
  class Lookahead : Unary<M> {
  public:
    using Unary<M>::Unary;
    const char* operator()(const char* b, const char* e) const {
      return this->m_(b, e) ? b : nullptr;
    }
  };

  template<typename M>
  constexpr Lookahead<M> operator&(const M& m) {
    return Lookahead<M> { m };
  }

  // Predicate

  template<typename P>
  class Predicate {
    const P p_;
  public:
    constexpr Predicate(const P& p) : p_(p) { }
    const char* operator()(const char* b, const char* e) const {
      return (b != e) && p_(*b) ? b+1 : nullptr;
    }
  };

  template<typename I, typename O>
  class Predicate<O(*)(I)> {
    O (*const p_)(I);
  public:
    constexpr Predicate(O (*const p)(I)) : p_(p) { }
    const char* operator()(const char* b, const char* e) const {
      return (b != e) && p_(*b) ? b+1 : nullptr;
    }
  };

  template<typename PT>
  constexpr Predicate<PT> P(const PT& p) {
    return Predicate<PT> { p };
  }

  template<typename I, typename O>
  constexpr Predicate<O(*)(I)> P(O (*const p)(I)) {
    return Predicate<O(*)(I)> { p };
  }

}

#endif<commit_msg>tweaks<commit_after>#ifndef MUNCHAR
#define MUNCHAR

#include <cstddef>

namespace Munchar {

  // Unconditional success

  struct Success {
    const char* operator()(const char* b, const char* e) const {
      return b;
    }
  };

  // Unconditional failure

  struct Failure {
    const char* operator()(const char* b, const char* e) const {
      return nullptr;
    }
  };

  // Arbitrary character

  struct Any_Char {
    const char* operator()(const char* b, const char* e) const {
      return b != e ? b+1 : nullptr;
    }
  };

  // Character constant

  class Char {
    const char c_;
  public:
    constexpr Char(const char c) : c_(c) { }
    const char* operator()(const char* b, const char* e) const {
      return b != e && *b == c_ ? b+1 : nullptr;
    }
  };

  constexpr Char operator"" _lit(const char c) {
    return Char { c };
  }

  // String constant

  template<typename Ptr = const char*>
  class Str {
    Ptr s_;
    size_t len_;
  public:
    constexpr Str(Ptr s, size_t len) : s_(s), len_(len) { }
    const char* operator()(const char* b, const char* e) const {
      Ptr s = s_;
      for (size_t i = 0; i < len_; ++i, ++b, ++s) {
        if ((b == e) || (*s_ != *b)) return nullptr;
      }
      return b;
    }
  };

  constexpr Str<> operator"" _lit(const char* c, size_t len) {
    return Str<> { c, len };
  }

  // Character class

  template<typename Ptr = const char*>
  class Char_Class {
    Ptr s_;
    size_t len_;
  public:
    constexpr Char_Class(Ptr s, size_t len) : s_(s), len_(len) { }
    const char* operator()(const char* b, const char* e) const {
      if (b == e) return nullptr;
      Ptr s = s_;
      for (size_t i = 0; i < len_; ++i, ++s) if (*s == *b) return b+1;
      return nullptr;
    }
  };

  constexpr Char_Class<> operator"" _cls(const char* c, size_t len) {
    return Char_Class<> { c, len };
  }

  // Base class for unary combinators

  template<typename M>
  class Unary {
  protected:
    const M m_;
  public:
    constexpr Unary(const M& m) : m_(m) { }
  };

  // Base class for binary combinators

  template<typename L, typename R>
  class Binary {
  protected:
    const L l_;
    const R r_;
  public:
    constexpr Binary(const L& l, const R& r) : l_(l), r_(r) { }
  };

  // Sequencing

  template<typename L, typename R>
  class Sequence : public Binary<L, R> {
  public:
    using Binary<L, R>::Binary;
    const char* operator()(const char* b, const char* e) const {
      return (b = this->l_(b, e)) ? this->r_(b, e) : nullptr;
    }
  };

  template<typename L, typename R>
  constexpr Sequence<L, R> operator^(const L& l, const R& r) {
    return Sequence<L, R> { l, r };
  }

  // Alternation

  template<typename L, typename R>
  class Alternation : public Binary<L, R> {
  public:
    using Binary<L, R>::Binary;
    const char* operator()(const char* b, const char* e) const {
      return (b = this->l_(b, e)) ? b : this->r_(b, e);
    }
  };

  template<typename L, typename R>
  constexpr Alternation<L, R> operator|(const L& l, const R& r) {
    return Alternation<L, R> { l, r };
  }

  // Option

  template<typename M>
  constexpr auto operator~(const M& m)
  -> decltype(m | Success { }) {
    return m | Success { };
  }

  // Repetition

  template<typename M>
  class Zero_Or_More : public Unary<M> {
  public:
    using Unary<M>::Unary;
    const char* operator()(const char* b, const char* e) const {
      for (const char* p = b; (p = this->m_(b, e)); b = p) ;
      return b;
    }
  };

  template<typename M>
  constexpr Zero_Or_More<M> operator*(const M& m) {
    return Zero_Or_More<M> { m };
  }

  template<typename M>
  constexpr auto operator+(const M& m)
  -> decltype(m ^ *m) {
    return m ^ *m;
  }

  // Bounded repetition

  template<typename M>
  class Exactly_N_Times : public Unary<M> {
    size_t n_;
  public:
    constexpr Exactly_N_Times(const M& m, size_t n) : Unary<M> { m }, n_(n) { }
    const char* operator()(const char* b, const char* e) const {
      size_t i;
      for (i = 0; i < n_ && (b = this->m_(b, e)); ++i) ;
      return i == n_ ? b : nullptr;
    }
  };

  template<typename M>
  constexpr Exactly_N_Times<M> operator==(const M& m,  size_t n) {
    return Exactly_N_Times<M> { m, n };
  }

  template<typename M>
  constexpr auto operator>(const M& m,  size_t n)
  -> decltype((m == n) ^ +m) {
    return (m == n) ^ +m;
  }

  template<typename M>
  constexpr auto operator>=(const M& m,  size_t n)
  -> decltype((m == n) ^ *m) {
    return (m == n) ^ *m;
  }

  template<typename M>
  constexpr auto operator<(const M& m,  size_t n)
  -> decltype((m == n-1) | *m) {
    return (m == n-1) | *m;
  }

  template<typename M>
  constexpr auto operator<=(const M& m,  size_t n)
  -> decltype((m == n) | *m) {
    return (m == n) | *m;
  }

  template<typename M>
  constexpr auto between(size_t a, size_t b, const M& m)
  -> decltype((m == a) ^ (m <= b)) {
    return (m == a) ^ (m <= b);
  }

  // Negation

  template<typename M>
  class Negation : Unary<M> {
  public:
    using Unary<M>::Unary;
    const char* operator()(const char* b, const char* e) const {
      return this->m_(b, e) ? nullptr : b;
    }
  };

  template<typename M>
  constexpr Negation<M> operator!(const M& m) {
    return Negation<M> { m };
  }

  // Lookahead

  template<typename M>
  class Lookahead : Unary<M> {
  public:
    using Unary<M>::Unary;
    const char* operator()(const char* b, const char* e) const {
      return this->m_(b, e) ? b : nullptr;
    }
  };

  template<typename M>
  constexpr Lookahead<M> operator&(const M& m) {
    return Lookahead<M> { m };
  }

  // Predicate

  template<typename P>
  class Predicate {
    const P p_;
  public:
    constexpr Predicate(const P& p) : p_(p) { }
    const char* operator()(const char* b, const char* e) const {
      return (b != e) && p_(*b) ? b+1 : nullptr;
    }
  };

  template<typename I, typename O>
  class Predicate<O (*)(I)> {
    O (*const p_)(I);
  public:
    constexpr Predicate(O (*const p)(I)) : p_(p) { }
    const char* operator()(const char* b, const char* e) const {
      return (b != e) && p_(*b) ? b+1 : nullptr;
    }
  };

  template<typename PT>
  constexpr Predicate<PT> P(const PT& p) {
    return Predicate<PT> { p };
  }

  template<typename I, typename O>
  constexpr Predicate<O (*)(I)> P(O (*const p)(I)) {
    return Predicate<O (*)(I)> { p };
  }

}

#endif<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_WINDOWS_SUBPROCESS_HPP__
#define __PROCESS_WINDOWS_SUBPROCESS_HPP__

#include <signal.h>

#include <string>

#include <glog/logging.h>

#include <process/subprocess.hpp>

#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/hashset.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/try.hpp>

#include <stout/os/close.hpp>
#include <stout/os/environment.hpp>

#include <userEnv.h>

namespace process {

using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;

namespace internal {

inline void close(const hashset<HANDLE>& fds)
{
  foreach (HANDLE fd, fds) {
    if (fd != INVALID_HANDLE_VALUE) {
      os::close(fd);
    }
  }
}

// This function will invoke `os::close` on all specified file
// descriptors that are valid (i.e., not `None` and >= 0).
inline void close(
    const InputFileDescriptors& stdinfds,
    const OutputFileDescriptors& stdoutfds,
    const OutputFileDescriptors& stderrfds)
{
  close({
    stdinfds.read,
    stdinfds.write.getOrElse(INVALID_HANDLE_VALUE),
    stdoutfds.read.getOrElse(INVALID_HANDLE_VALUE),
    stdoutfds.write,
    stderrfds.read.getOrElse(INVALID_HANDLE_VALUE),
    stderrfds.write
  });
}

// Retrieves system environment in a `std::map`, ignoring
// the current process's environment variables.
inline Option<map<string, string>> getSystemEnvironment()
{
  std::wstring_convert<std::codecvt<wchar_t, char, mbstate_t>,
    wchar_t> converter;

  map<string, string> systemEnvironment;
  wchar_t* environmentEntry = nullptr;

  // Get the system environment.
  // The third parameter (bool) tells the function *not* to inherit
  // variables from the current process.
  if (!CreateEnvironmentBlock((LPVOID*)&environmentEntry, nullptr, FALSE)) {
    return None();
  }

  // Save the environment block in order to destroy it later.
  wchar_t* environmentBlock = environmentEntry;

  while (*environmentEntry != L'\0') {
    // Each environment block contains the environment variables as follows:
    // Var1=Value1\0
    // Var2=Value2\0
    // Var3=Value3\0
    // ...
    // VarN=ValueN\0\0
    // The name of an environment variable cannot include an equal sign (=).

    wchar_t * separator = wcschr(environmentEntry, L'=');
    std::wstring varName = std::wstring(environmentEntry, separator);
    std::wstring varVal = std::wstring(separator + 1);

    // Mesos variables are upper case. Convert system variables to
    // match the name provided by the scheduler in case of a collision.
    std::transform(varName.begin(), varName.end(), varName.begin(), ::towupper);

    // The system environment has priority. Force `ANSI` usage until the code
    // is converted to UNICODE.
    systemEnvironment.insert_or_assign(
      converter.to_bytes(varName.c_str()),
      converter.to_bytes(varVal.c_str()));

    environmentEntry += varName.length() + varVal.length() + 2;
  }

  DestroyEnvironmentBlock(environmentBlock);

  return systemEnvironment;
}

// Creates a null-terminated array of null-terminated strings that will be
// passed to `CreateProcess` as the `lpEnvironment` argument, as described by
// MSDN[1]. This array needs to be sorted in alphabetical order, but the `map`
// already takes care of that. Note that this function does not handle Unicode
// environments, so it should not be used in conjunction with the
// `CREATE_UNICODE_ENVIRONMENT` flag.
//
// NOTE: This function will add the system's environment variables into
// the returned string. These variables take precedence over the provided
// `env` and are generally necessary in order to launch things on Windows.
//
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
inline Option<string> createProcessEnvironment(
    const Option<map<string, string>>& env)
{
  if (env.isNone() || (env.isSome() && env.get().size() == 0)) {
    return None();
  }

  Option<map<string, string>> systemEnvironment = getSystemEnvironment();

  // The system environment must be non-empty.
  // No subprocesses will be able to launch if the system environment is blank.
  CHECK(systemEnvironment.isSome() && systemEnvironment.get().size() > 0);

  map<string, string> combinedEnvironment = env.get();

  foreachpair(const string& key, const string& value, systemEnvironment.get()) {
    combinedEnvironment[key] = value;
  }

  string environmentString;
  foreachpair (const string& key, const string& value, combinedEnvironment) {
    environmentString += key + '=' + value + '\0';
  }

  return environmentString;
}

inline Try<PROCESS_INFORMATION> createChildProcess(
    const string& path,
    const vector<string>& argv,
    const Option<map<string, string>>& environment,
    const InputFileDescriptors stdinfds,
    const OutputFileDescriptors stdoutfds,
    const OutputFileDescriptors stderrfds)
{
  // Construct the environment that will be passed to `CreateProcess`.
  Option<string> environmentString = createProcessEnvironment(environment);
  const char* processEnvironment = environmentString.isNone()
    ? nullptr
    : environmentString.get().c_str();

  PROCESS_INFORMATION processInfo;
  STARTUPINFO startupInfo;

  ::ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
  ::ZeroMemory(&startupInfo, sizeof(STARTUPINFO));

  // Hook up the `stdin`/`stdout`/`stderr` pipes and use the
  // `STARTF_USESTDHANDLES` flag to instruct the child to use them[1]. A more
  // user-friendly example can be found in [2].
  //
  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx
  // [2] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
  startupInfo.cb = sizeof(STARTUPINFO);
  startupInfo.hStdInput = stdinfds.read;
  startupInfo.hStdOutput = stdoutfds.write;
  startupInfo.hStdError = stderrfds.write;
  startupInfo.dwFlags |= STARTF_USESTDHANDLES;

  // Build command to pass to `::CreateProcess`.
  //
  // NOTE: We are expecting that components of `argv` that need to be quoted
  // (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`)
  // to have been already quoted correctly before we generate `command`.
  // Incorrectly-quoted command arguments will probably lead the child process
  // to terminate with an error. See also NOTE on `process::subprocess`.
  string command = strings::join(" ", argv);

  // Escape the quotes in `command`.
  //
  // TODO(dpravat): Add tests cases that cover this functionality. See
  // MESOS-5418.
  command = strings::replace(command, "\"", "\\\"");

  // NOTE: If Mesos is built against the ANSI version of this function, the
  // environment is limited to 32,767 characters. See[1].
  //
  // TODO(hausdorff): Figure out how to map the `path` and `args` arguments of
  // this function into a call to `::CreateProcess` that is more general
  // purpose. In particular, on POSIX, we expect that calls to `subprocess` can
  // be called with relative `path` (e.g., it could simply be `sh`). However,
  // on Windows, unlike the calls to (e.g.) `exec`, `::CreateProcess` will
  // expect that this argument be a fully-qualified path. In the end, we'd like
  // the calls to `subprocess` to have similar command formats to minimize
  // confusion and mistakes.
  //
  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
  BOOL createProcessResult = CreateProcess(
      nullptr,
      (LPSTR)command.data(),
      nullptr,                 // Default security attributes.
      nullptr,                 // Default primary thread security attributes.
      TRUE,                    // Inherited parent process handles.
      0,                       // Normal thread priority.
      (LPVOID)processEnvironment,
      nullptr,                 // Use parent's current directory.
      &startupInfo,            // STARTUPINFO pointer.
      &processInfo);           // PROCESS_INFORMATION pointer.

  if (!createProcessResult) {
    return WindowsError("createChildProcess: failed to call 'CreateProcess'");
  }

  return processInfo;
}

}  // namespace internal {
}  // namespace process {

#endif // __PROCESS_WINDOWS_SUBPROCESS_HPP__
<commit_msg>Windows: Qualified string, map, and vector in `subprocess.hpp`.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_WINDOWS_SUBPROCESS_HPP__
#define __PROCESS_WINDOWS_SUBPROCESS_HPP__

#include <signal.h>

#include <string>

#include <glog/logging.h>

#include <process/subprocess.hpp>

#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/hashset.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/try.hpp>

#include <stout/os/close.hpp>
#include <stout/os/environment.hpp>

#include <userEnv.h>

namespace process {

using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;

namespace internal {

inline void close(const hashset<HANDLE>& fds)
{
  foreach (HANDLE fd, fds) {
    if (fd != INVALID_HANDLE_VALUE) {
      os::close(fd);
    }
  }
}

// This function will invoke `os::close` on all specified file
// descriptors that are valid (i.e., not `None` and >= 0).
inline void close(
    const InputFileDescriptors& stdinfds,
    const OutputFileDescriptors& stdoutfds,
    const OutputFileDescriptors& stderrfds)
{
  close({
    stdinfds.read,
    stdinfds.write.getOrElse(INVALID_HANDLE_VALUE),
    stdoutfds.read.getOrElse(INVALID_HANDLE_VALUE),
    stdoutfds.write,
    stderrfds.read.getOrElse(INVALID_HANDLE_VALUE),
    stderrfds.write
  });
}

// Retrieves system environment in a `std::map`, ignoring
// the current process's environment variables.
inline Option<std::map<std::string, std::string>> getSystemEnvironment()
{
  std::wstring_convert<std::codecvt<wchar_t, char, mbstate_t>,
    wchar_t> converter;

  std::map<std::string, std::string> systemEnvironment;
  wchar_t* environmentEntry = nullptr;

  // Get the system environment.
  // The third parameter (bool) tells the function *not* to inherit
  // variables from the current process.
  if (!CreateEnvironmentBlock((LPVOID*)&environmentEntry, nullptr, FALSE)) {
    return None();
  }

  // Save the environment block in order to destroy it later.
  wchar_t* environmentBlock = environmentEntry;

  while (*environmentEntry != L'\0') {
    // Each environment block contains the environment variables as follows:
    // Var1=Value1\0
    // Var2=Value2\0
    // Var3=Value3\0
    // ...
    // VarN=ValueN\0\0
    // The name of an environment variable cannot include an equal sign (=).

    wchar_t * separator = wcschr(environmentEntry, L'=');
    std::wstring varName = std::wstring(environmentEntry, separator);
    std::wstring varVal = std::wstring(separator + 1);

    // Mesos variables are upper case. Convert system variables to
    // match the name provided by the scheduler in case of a collision.
    std::transform(varName.begin(), varName.end(), varName.begin(), ::towupper);

    // The system environment has priority. Force `ANSI` usage until the code
    // is converted to UNICODE.
    systemEnvironment.insert_or_assign(
      converter.to_bytes(varName.c_str()),
      converter.to_bytes(varVal.c_str()));

    environmentEntry += varName.length() + varVal.length() + 2;
  }

  DestroyEnvironmentBlock(environmentBlock);

  return systemEnvironment;
}

// Creates a null-terminated array of null-terminated strings that will be
// passed to `CreateProcess` as the `lpEnvironment` argument, as described by
// MSDN[1]. This array needs to be sorted in alphabetical order, but the `map`
// already takes care of that. Note that this function does not handle Unicode
// environments, so it should not be used in conjunction with the
// `CREATE_UNICODE_ENVIRONMENT` flag.
//
// NOTE: This function will add the system's environment variables into
// the returned string. These variables take precedence over the provided
// `env` and are generally necessary in order to launch things on Windows.
//
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
inline Option<std::string> createProcessEnvironment(
    const Option<std::map<std::string, std::string>>& env)
{
  if (env.isNone() || (env.isSome() && env.get().size() == 0)) {
    return None();
  }

  Option<std::map<std::string, std::string>> systemEnvironment =
    getSystemEnvironment();

  // The system environment must be non-empty.
  // No subprocesses will be able to launch if the system environment is blank.
  CHECK(systemEnvironment.isSome() && systemEnvironment.get().size() > 0);

  std::map<std::string, std::string> combinedEnvironment = env.get();

  foreachpair (const std::string& key,
               const std::string& value,
               systemEnvironment.get()) {
    combinedEnvironment[key] = value;
  }

  std::string environmentString;
  foreachpair (const std::string& key,
               const std::string& value,
               combinedEnvironment) {
    environmentString += key + '=' + value + '\0';
  }

  return environmentString;
}

inline Try<PROCESS_INFORMATION> createChildProcess(
    const std::string& path,
    const std::vector<std::string>& argv,
    const Option<std::map<std::string, std::string>>& environment,
    const InputFileDescriptors stdinfds,
    const OutputFileDescriptors stdoutfds,
    const OutputFileDescriptors stderrfds)
{
  // Construct the environment that will be passed to `CreateProcess`.
  Option<std::string> environmentString = createProcessEnvironment(environment);
  const char* processEnvironment = environmentString.isNone()
    ? nullptr
    : environmentString.get().c_str();

  PROCESS_INFORMATION processInfo;
  STARTUPINFO startupInfo;

  ::ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
  ::ZeroMemory(&startupInfo, sizeof(STARTUPINFO));

  // Hook up the `stdin`/`stdout`/`stderr` pipes and use the
  // `STARTF_USESTDHANDLES` flag to instruct the child to use them[1]. A more
  // user-friendly example can be found in [2].
  //
  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx
  // [2] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
  startupInfo.cb = sizeof(STARTUPINFO);
  startupInfo.hStdInput = stdinfds.read;
  startupInfo.hStdOutput = stdoutfds.write;
  startupInfo.hStdError = stderrfds.write;
  startupInfo.dwFlags |= STARTF_USESTDHANDLES;

  // Build command to pass to `::CreateProcess`.
  //
  // NOTE: We are expecting that components of `argv` that need to be quoted
  // (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`)
  // to have been already quoted correctly before we generate `command`.
  // Incorrectly-quoted command arguments will probably lead the child process
  // to terminate with an error. See also NOTE on `process::subprocess`.
  std::string command = strings::join(" ", argv);

  // Escape the quotes in `command`.
  //
  // TODO(dpravat): Add tests cases that cover this functionality. See
  // MESOS-5418.
  command = strings::replace(command, "\"", "\\\"");

  // NOTE: If Mesos is built against the ANSI version of this function, the
  // environment is limited to 32,767 characters. See[1].
  //
  // TODO(hausdorff): Figure out how to map the `path` and `args` arguments of
  // this function into a call to `::CreateProcess` that is more general
  // purpose. In particular, on POSIX, we expect that calls to `subprocess` can
  // be called with relative `path` (e.g., it could simply be `sh`). However,
  // on Windows, unlike the calls to (e.g.) `exec`, `::CreateProcess` will
  // expect that this argument be a fully-qualified path. In the end, we'd like
  // the calls to `subprocess` to have similar command formats to minimize
  // confusion and mistakes.
  //
  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
  BOOL createProcessResult = CreateProcess(
      nullptr,
      (LPSTR)command.data(),
      nullptr,                 // Default security attributes.
      nullptr,                 // Default primary thread security attributes.
      TRUE,                    // Inherited parent process handles.
      0,                       // Normal thread priority.
      (LPVOID)processEnvironment,
      nullptr,                 // Use parent's current directory.
      &startupInfo,            // STARTUPINFO pointer.
      &processInfo);           // PROCESS_INFORMATION pointer.

  if (!createProcessResult) {
    return WindowsError("createChildProcess: failed to call 'CreateProcess'");
  }

  return processInfo;
}

}  // namespace internal {
}  // namespace process {

#endif // __PROCESS_WINDOWS_SUBPROCESS_HPP__
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlgname.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 04:18:08 $
 *
 *  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_svx.hxx"

#ifdef SVX_DLLIMPLEMENTATION
#undef SVX_DLLIMPLEMENTATION
#endif

#include <tools/ref.hxx>
#include <tools/list.hxx>
#ifndef _SHL_HXX
#include <tools/shl.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif

#include "dialogs.hrc"

#include "dlgname.hxx"
#include "defdlgname.hxx" //CHINA001
#include "dlgname.hrc"
#include "dialmgr.hxx"

#define MAX_DESCRIPTION_LINES   ((long)5)

/*************************************************************************
|*
|* Dialog zum Editieren eines Namens
|*
\************************************************************************/

SvxNameDialog::SvxNameDialog( Window* pWindow, const String& rName, const String& rDesc ) :
    ModalDialog     ( pWindow, ResId( RID_SVXDLG_NAME, DIALOG_MGR() ) ),
    aFtDescription      ( this, ResId( FT_DESCRIPTION ) ),
    aEdtName            ( this, ResId( EDT_STRING ) ),
    aBtnOK              ( this, ResId( BTN_OK ) ),
    aBtnCancel          ( this, ResId( BTN_CANCEL ) ),
    aBtnHelp            ( this, ResId( BTN_HELP ) )
{
    FreeResource();

    aFtDescription.SetText( rDesc );
    aEdtName.SetText( rName );
    aEdtName.SetSelection(Selection(SELECTION_MIN, SELECTION_MAX));
    ModifyHdl(&aEdtName);
    aEdtName.SetModifyHdl(LINK(this, SvxNameDialog, ModifyHdl));

    // dynamic height of the description field
    Size aSize = aFtDescription.GetSizePixel();
    long nTxtWidth = aFtDescription.GetCtrlTextWidth( rDesc );
    if ( nTxtWidth > aSize.Width() )
    {
        long nLines = Min( ( nTxtWidth / aSize.Width() + 1 ), MAX_DESCRIPTION_LINES );
        long nHeight = aSize.Height();
        aSize.Height() = nHeight * nLines;
        aFtDescription.SetSizePixel( aSize );
        Point aPnt = aEdtName.GetPosPixel();
        aPnt.Y() += ( aSize.Height() - nHeight );
        aEdtName.SetPosPixel( aPnt );
    }
}

/* -----------------------------27.02.2002 15:22------------------------------

 ---------------------------------------------------------------------------*/
IMPL_LINK(SvxNameDialog, ModifyHdl, Edit*, EMPTYARG)
{
    if(aCheckNameHdl.IsSet())
        aBtnOK.Enable(aCheckNameHdl.Call(this) > 0);
    return 0;
}

/*************************************************************************
|*
|* Dialog zum Abbrechen, Speichern oder Hinzufuegen
|*
\************************************************************************/

SvxMessDialog::SvxMessDialog( Window* pWindow, const String& rText, const String& rDesc, Image* pImg ) :
    ModalDialog     ( pWindow, ResId( RID_SVXDLG_MESSBOX, DIALOG_MGR() ) ),
    aFtDescription      ( this, ResId( FT_DESCRIPTION ) ),
    aBtn1               ( this, ResId( BTN_1 ) ),
    aBtn2               ( this, ResId( BTN_2 ) ),
    aBtnCancel          ( this, ResId( BTN_CANCEL ) ),
    aFtImage            ( this )
{
    FreeResource();

    if( pImg )
    {
        pImage = new Image( *pImg );
        aFtImage.SetImage( *pImage );
        aFtImage.SetStyle( ( aFtImage.GetStyle()/* | WB_NOTABSTOP */) & ~WB_3DLOOK );
        aFtImage.SetPosSizePixel( LogicToPixel( Point( 3, 6 ), MAP_APPFONT ),
                                  aFtImage.GetImage().GetSizePixel() );
        aFtImage.Show();
    }

    SetText( rText );
    aFtDescription.SetText( rDesc );

    aBtn1.SetClickHdl( LINK( this, SvxMessDialog, Button1Hdl ) );
    aBtn2.SetClickHdl( LINK( this, SvxMessDialog, Button2Hdl ) );
}

SvxMessDialog::~SvxMessDialog()
{
    if( pImage )
        delete pImage;
}

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

IMPL_LINK_INLINE_START( SvxMessDialog, Button1Hdl, Button *, EMPTYARG )
{
    EndDialog( RET_BTN_1 );
    return 0;
}
IMPL_LINK_INLINE_END( SvxMessDialog, Button1Hdl, Button *, EMPTYARG )

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

IMPL_LINK_INLINE_START( SvxMessDialog, Button2Hdl, Button *, EMPTYARG )
{
    EndDialog( RET_BTN_2 );
    return 0;
}
IMPL_LINK_INLINE_END( SvxMessDialog, Button2Hdl, Button *, EMPTYARG )

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

void SvxMessDialog::SetButtonText( USHORT nBtnId, const String& rNewTxt )
{
    switch ( nBtnId )
    {
        case MESS_BTN_1:
            aBtn1.SetText( rNewTxt );
            break;

        case MESS_BTN_2:
            aBtn2.SetText( rNewTxt );
            break;

        default:
            DBG_ERROR( "Falsche Button-Nummer!!!" );
    }
}

<commit_msg>INTEGRATION: CWS aw038 (1.9.150); FILE MERGED 2006/12/06 15:53:59 aw 1.9.150.3: #i68101# adapted dialogs for ObjectName and ObjectTitleDescription 2006/12/05 10:33:58 aw 1.9.150.2: #i68101# 2nd version of dialogs 2006/12/01 17:43:06 aw 1.9.150.1: #i68101# SdrObject core support for Title, Description added, support for Name reworked. UNO API support for Title Description added as xShape property. Rudimentary created new NameTitleDesc dialog<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlgname.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: ihi $ $Date: 2006-12-19 17:45:38 $
 *
 *  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_svx.hxx"

#ifdef SVX_DLLIMPLEMENTATION
#undef SVX_DLLIMPLEMENTATION
#endif

#include <tools/ref.hxx>
#include <tools/list.hxx>
#ifndef _SHL_HXX
#include <tools/shl.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif

#include "dialogs.hrc"

#include "dlgname.hxx"
#include "defdlgname.hxx" //CHINA001
#include "dlgname.hrc"
#include "dialmgr.hxx"

#define MAX_DESCRIPTION_LINES   ((long)5)

/*************************************************************************
|*
|* Dialog zum Editieren eines Namens
|*
\************************************************************************/

SvxNameDialog::SvxNameDialog( Window* pWindow, const String& rName, const String& rDesc ) :
    ModalDialog     ( pWindow, ResId( RID_SVXDLG_NAME, DIALOG_MGR() ) ),
    aFtDescription      ( this, ResId( FT_DESCRIPTION ) ),
    aEdtName            ( this, ResId( EDT_STRING ) ),
    aBtnOK              ( this, ResId( BTN_OK ) ),
    aBtnCancel          ( this, ResId( BTN_CANCEL ) ),
    aBtnHelp            ( this, ResId( BTN_HELP ) )
{
    FreeResource();

    aFtDescription.SetText( rDesc );
    aEdtName.SetText( rName );
    aEdtName.SetSelection(Selection(SELECTION_MIN, SELECTION_MAX));
    ModifyHdl(&aEdtName);
    aEdtName.SetModifyHdl(LINK(this, SvxNameDialog, ModifyHdl));

    // dynamic height of the description field
    Size aSize = aFtDescription.GetSizePixel();
    long nTxtWidth = aFtDescription.GetCtrlTextWidth( rDesc );
    if ( nTxtWidth > aSize.Width() )
    {
        long nLines = Min( ( nTxtWidth / aSize.Width() + 1 ), MAX_DESCRIPTION_LINES );
        long nHeight = aSize.Height();
        aSize.Height() = nHeight * nLines;
        aFtDescription.SetSizePixel( aSize );
        Point aPnt = aEdtName.GetPosPixel();
        aPnt.Y() += ( aSize.Height() - nHeight );
        aEdtName.SetPosPixel( aPnt );
    }
}

/* -----------------------------27.02.2002 15:22------------------------------

 ---------------------------------------------------------------------------*/
IMPL_LINK(SvxNameDialog, ModifyHdl, Edit*, EMPTYARG)
{
    if(aCheckNameHdl.IsSet())
        aBtnOK.Enable(aCheckNameHdl.Call(this) > 0);
    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////
// #i68101#
// Dialog for editing Object Name
// plus uniqueness-callback-linkHandler

SvxObjectNameDialog::SvxObjectNameDialog(
    Window* pWindow,
    const String& rName)
:   ModalDialog(pWindow, ResId(RID_SVXDLG_OBJECT_NAME, DIALOG_MGR())),
    aFtName(this, ResId(NTD_FT_NAME)),
    aEdtName(this, ResId(NTD_EDT_NAME)),
    aFlSeparator(this, ResId(FL_SEPARATOR_A)),
    aBtnHelp(this, ResId(BTN_HELP)),
    aBtnOK(this, ResId(BTN_OK)),
    aBtnCancel(this, ResId(BTN_CANCEL))
{
    FreeResource();

    // set name
    aEdtName.SetText(rName);

    // activate name
    aEdtName.SetSelection(Selection(SELECTION_MIN, SELECTION_MAX));
    ModifyHdl(&aEdtName);
    aEdtName.SetModifyHdl(LINK(this, SvxObjectNameDialog, ModifyHdl));
}

IMPL_LINK(SvxObjectNameDialog, ModifyHdl, Edit*, EMPTYARG)
{
    if(aCheckNameHdl.IsSet())
    {
        aBtnOK.Enable(aCheckNameHdl.Call(this) > 0);
    }

    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////
// #i68101#
// Dialog for editing Object Title and Description

SvxObjectTitleDescDialog::SvxObjectTitleDescDialog(
    Window* pWindow,
    const String& rTitle,
    const String& rDescription)
:   ModalDialog(pWindow, ResId(RID_SVXDLG_OBJECT_TITLE_DESC, DIALOG_MGR())),
    aFtTitle(this, ResId(NTD_FT_TITLE)),
    aEdtTitle(this, ResId(NTD_EDT_TITLE)),
    aFtDescription(this, ResId(NTD_FT_DESC)),
    aEdtDescription(this, ResId(NTD_EDT_DESC)),
    aFlSeparator(this, ResId(FL_SEPARATOR_B)),
    aBtnHelp(this, ResId(BTN_HELP)),
    aBtnOK(this, ResId(BTN_OK)),
    aBtnCancel(this, ResId(BTN_CANCEL))
{
    FreeResource();

    // set title & desc
    aEdtTitle.SetText(rTitle);
    aEdtDescription.SetText(rDescription);

    // activate title
    aEdtTitle.SetSelection(Selection(SELECTION_MIN, SELECTION_MAX));
}

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

/*************************************************************************
|*
|* Dialog zum Abbrechen, Speichern oder Hinzufuegen
|*
\************************************************************************/

SvxMessDialog::SvxMessDialog( Window* pWindow, const String& rText, const String& rDesc, Image* pImg ) :
    ModalDialog     ( pWindow, ResId( RID_SVXDLG_MESSBOX, DIALOG_MGR() ) ),
    aFtDescription      ( this, ResId( FT_DESCRIPTION ) ),
    aBtn1               ( this, ResId( BTN_1 ) ),
    aBtn2               ( this, ResId( BTN_2 ) ),
    aBtnCancel          ( this, ResId( BTN_CANCEL ) ),
    aFtImage            ( this )
{
    FreeResource();

    if( pImg )
    {
        pImage = new Image( *pImg );
        aFtImage.SetImage( *pImage );
        aFtImage.SetStyle( ( aFtImage.GetStyle()/* | WB_NOTABSTOP */) & ~WB_3DLOOK );
        aFtImage.SetPosSizePixel( LogicToPixel( Point( 3, 6 ), MAP_APPFONT ),
                                  aFtImage.GetImage().GetSizePixel() );
        aFtImage.Show();
    }

    SetText( rText );
    aFtDescription.SetText( rDesc );

    aBtn1.SetClickHdl( LINK( this, SvxMessDialog, Button1Hdl ) );
    aBtn2.SetClickHdl( LINK( this, SvxMessDialog, Button2Hdl ) );
}

SvxMessDialog::~SvxMessDialog()
{
    if( pImage )
        delete pImage;
}

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

IMPL_LINK_INLINE_START( SvxMessDialog, Button1Hdl, Button *, EMPTYARG )
{
    EndDialog( RET_BTN_1 );
    return 0;
}
IMPL_LINK_INLINE_END( SvxMessDialog, Button1Hdl, Button *, EMPTYARG )

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

IMPL_LINK_INLINE_START( SvxMessDialog, Button2Hdl, Button *, EMPTYARG )
{
    EndDialog( RET_BTN_2 );
    return 0;
}
IMPL_LINK_INLINE_END( SvxMessDialog, Button2Hdl, Button *, EMPTYARG )

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

void SvxMessDialog::SetButtonText( USHORT nBtnId, const String& rNewTxt )
{
    switch ( nBtnId )
    {
        case MESS_BTN_1:
            aBtn1.SetText( rNewTxt );
            break;

        case MESS_BTN_2:
            aBtn2.SetText( rNewTxt );
            break;

        default:
            DBG_ERROR( "Falsche Button-Nummer!!!" );
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <iostream>

#include "mutation_partition.hh"
#include "keys.hh"
#include "schema.hh"
#include "dht/i_partitioner.hh"

class mutation final {
private:
    schema_ptr _schema;
    dht::decorated_key _dk;
    mutation_partition _p;
public:
    mutation(dht::decorated_key key, schema_ptr schema);
    mutation(partition_key key, schema_ptr schema);
    mutation(schema_ptr schema, dht::decorated_key key, mutation_partition mp);
    mutation(mutation&&) = default;
    mutation(const mutation&) = default;
    mutation& operator=(mutation&& x) = default;

    void set_static_cell(const column_definition& def, atomic_cell_or_collection value);
    void set_static_cell(const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value);
    void set_clustered_cell(const clustering_key& key, const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection value);
    void set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value);
    std::experimental::optional<atomic_cell_or_collection> get_cell(const clustering_key& rkey, const column_definition& def) const;
    const partition_key& key() const { return _dk._key; };
    const dht::decorated_key& decorated_key() const { return _dk; };
    const dht::token token() const { return _dk._token; }
    const schema_ptr& schema() const { return _schema; }
    const mutation_partition& partition() const { return _p; }
    mutation_partition& partition() { return _p; }
    const utils::UUID& column_family_id() const { return _schema->id(); }
    bool operator==(const mutation&) const;
    bool operator!=(const mutation&) const;
public:
    query::result query(const query::partition_slice&, gc_clock::time_point now = gc_clock::now(), uint32_t row_limit = query::max_rows) const;

    // See mutation_partition::live_row_count()
    size_t live_row_count(gc_clock::time_point query_time = gc_clock::time_point::min()) const;
private:
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
};

struct mutation_decorated_key_less_comparator {
    bool operator()(const mutation& m1, const mutation& m2) const;
};

using mutation_opt = std::experimental::optional<mutation>;

inline
void apply(mutation_opt& dst, mutation&& src) {
    if (!dst) {
        dst = std::move(src);
    } else {
        dst->partition().apply(*src.schema(), src.partition());
    }
}

inline
void apply(mutation_opt& dst, mutation_opt&& src) {
    if (src) {
        apply(dst, std::move(*src));
    }
}

// Returns a range into partitions containing mutations covered by the range.
// partitions must be sorted according to decorated key.
// range must not wrap around.
boost::iterator_range<std::vector<mutation>::const_iterator> slice(
    const std::vector<mutation>& partitions,
    const query::partition_range&);
<commit_msg>mutation: Fix token() getter<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <iostream>

#include "mutation_partition.hh"
#include "keys.hh"
#include "schema.hh"
#include "dht/i_partitioner.hh"

class mutation final {
private:
    schema_ptr _schema;
    dht::decorated_key _dk;
    mutation_partition _p;
public:
    mutation(dht::decorated_key key, schema_ptr schema);
    mutation(partition_key key, schema_ptr schema);
    mutation(schema_ptr schema, dht::decorated_key key, mutation_partition mp);
    mutation(mutation&&) = default;
    mutation(const mutation&) = default;
    mutation& operator=(mutation&& x) = default;

    void set_static_cell(const column_definition& def, atomic_cell_or_collection value);
    void set_static_cell(const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value);
    void set_clustered_cell(const clustering_key& key, const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection value);
    void set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value);
    std::experimental::optional<atomic_cell_or_collection> get_cell(const clustering_key& rkey, const column_definition& def) const;
    const partition_key& key() const { return _dk._key; };
    const dht::decorated_key& decorated_key() const { return _dk; };
    const dht::token& token() const { return _dk._token; }
    const schema_ptr& schema() const { return _schema; }
    const mutation_partition& partition() const { return _p; }
    mutation_partition& partition() { return _p; }
    const utils::UUID& column_family_id() const { return _schema->id(); }
    bool operator==(const mutation&) const;
    bool operator!=(const mutation&) const;
public:
    query::result query(const query::partition_slice&, gc_clock::time_point now = gc_clock::now(), uint32_t row_limit = query::max_rows) const;

    // See mutation_partition::live_row_count()
    size_t live_row_count(gc_clock::time_point query_time = gc_clock::time_point::min()) const;
private:
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
};

struct mutation_decorated_key_less_comparator {
    bool operator()(const mutation& m1, const mutation& m2) const;
};

using mutation_opt = std::experimental::optional<mutation>;

inline
void apply(mutation_opt& dst, mutation&& src) {
    if (!dst) {
        dst = std::move(src);
    } else {
        dst->partition().apply(*src.schema(), src.partition());
    }
}

inline
void apply(mutation_opt& dst, mutation_opt&& src) {
    if (src) {
        apply(dst, std::move(*src));
    }
}

// Returns a range into partitions containing mutations covered by the range.
// partitions must be sorted according to decorated key.
// range must not wrap around.
boost::iterator_range<std::vector<mutation>::const_iterator> slice(
    const std::vector<mutation>& partitions,
    const query::partition_range&);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <iostream>

#include "mutation_partition.hh"
#include "keys.hh"
#include "schema.hh"
#include "dht/i_partitioner.hh"

class mutation final {
private:
    struct data {
        schema_ptr _schema;
        dht::decorated_key _dk;
        mutation_partition _p;

        data(dht::decorated_key&& key, schema_ptr&& schema);
        data(partition_key&& key, schema_ptr&& schema);
        data(schema_ptr&& schema, dht::decorated_key&& key, const mutation_partition& mp);
        data(schema_ptr&& schema, dht::decorated_key&& key, mutation_partition&& mp);
    };
    std::unique_ptr<data> _ptr;
private:
    mutation() = default;
public:
    mutation(dht::decorated_key key, schema_ptr schema)
        : _ptr(std::make_unique<data>(std::move(key), std::move(schema)))
    { }
    mutation(partition_key key_, schema_ptr schema)
        : _ptr(std::make_unique<data>(std::move(key_), std::move(schema)))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, const mutation_partition& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), mp))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, mutation_partition&& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), std::move(mp)))
    { }
    mutation(const mutation& m)
        : _ptr(std::make_unique<data>(schema_ptr(m.schema()), dht::decorated_key(m.decorated_key()), m.partition()))
    { }

    mutation(mutation&&) = default;
    mutation& operator=(mutation&& x) = default;

    void set_static_cell(const column_definition& def, atomic_cell_or_collection&& value);
    void set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value);
    void set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value);
    void set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value);
    std::experimental::optional<atomic_cell_or_collection> get_cell(const clustering_key& rkey, const column_definition& def) const;
    const partition_key& key() const { return _ptr->_dk._key; };
    const dht::decorated_key& decorated_key() const { return _ptr->_dk; };
    const dht::token& token() const { return _ptr->_dk._token; }
    const schema_ptr& schema() const { return _ptr->_schema; }
    const mutation_partition& partition() const { return _ptr->_p; }
    mutation_partition& partition() { return _ptr->_p; }
    const utils::UUID& column_family_id() const { return _ptr->_schema->id(); }
    bool operator==(const mutation&) const;
    bool operator!=(const mutation&) const;
public:
    query::result query(const query::partition_slice&, gc_clock::time_point now = gc_clock::now(), uint32_t row_limit = query::max_rows) const;

    // See mutation_partition::live_row_count()
    size_t live_row_count(gc_clock::time_point query_time = gc_clock::time_point::min()) const;
private:
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
    friend class mutation_opt;
};

struct mutation_decorated_key_less_comparator {
    bool operator()(const mutation& m1, const mutation& m2) const;
};

class mutation_opt {
private:
    mutation _mutation;
public:
    mutation_opt() = default;
    mutation_opt(std::experimental::nullopt_t) noexcept { }
    mutation_opt(const mutation& obj) : _mutation(obj) { }
    mutation_opt(mutation&& obj) noexcept : _mutation(std::move(obj)) { }
    mutation_opt(std::experimental::optional<mutation>&& obj) noexcept {
        if (obj) {
            _mutation = std::move(*obj);
        }
    }
    mutation_opt(const mutation_opt&) = default;
    mutation_opt(mutation_opt&&) = default;

    mutation_opt& operator=(std::experimental::nullopt_t) noexcept {
        _mutation = mutation();
        return *this;
    }
    template<typename T>
    std::enable_if_t<std::is_same<std::decay_t<T>, mutation>::value, mutation_opt&>
    operator=(T&& obj) noexcept {
        _mutation = std::forward<T>(obj);
        return *this;
    }
    mutation_opt& operator=(mutation_opt&&) = default;

    explicit operator bool() const noexcept {
        return bool(_mutation._ptr);
    }

    mutation* operator->() noexcept { return &_mutation; }
    const mutation* operator->() const noexcept { return &_mutation; }

    mutation& operator*() noexcept { return _mutation; }
    const mutation& operator*() const noexcept { return _mutation; }

    bool operator==(const mutation_opt& other) const {
        if (!*this && !other) {
            return true;
        }
        if (!*this || !other) {
            return false;
        }
        return _mutation == other._mutation;
    }
    bool operator!=(const mutation_opt& other) const {
        return !(*this == other);
    }
};

inline mutation_opt move_and_disengage(mutation_opt& opt) {
    return std::move(opt);
}

inline
void apply(mutation_opt& dst, mutation&& src) {
    if (!dst) {
        dst = std::move(src);
    } else {
        dst->partition().apply(*src.schema(), src.partition());
    }
}

inline
void apply(mutation_opt& dst, mutation_opt&& src) {
    if (src) {
        apply(dst, std::move(*src));
    }
}

// Returns a range into partitions containing mutations covered by the range.
// partitions must be sorted according to decorated key.
// range must not wrap around.
boost::iterator_range<std::vector<mutation>::const_iterator> slice(
    const std::vector<mutation>& partitions,
    const query::partition_range&);
<commit_msg>mutation: Introduce ring_position()<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <iostream>

#include "mutation_partition.hh"
#include "keys.hh"
#include "schema.hh"
#include "dht/i_partitioner.hh"

class mutation final {
private:
    struct data {
        schema_ptr _schema;
        dht::decorated_key _dk;
        mutation_partition _p;

        data(dht::decorated_key&& key, schema_ptr&& schema);
        data(partition_key&& key, schema_ptr&& schema);
        data(schema_ptr&& schema, dht::decorated_key&& key, const mutation_partition& mp);
        data(schema_ptr&& schema, dht::decorated_key&& key, mutation_partition&& mp);
    };
    std::unique_ptr<data> _ptr;
private:
    mutation() = default;
public:
    mutation(dht::decorated_key key, schema_ptr schema)
        : _ptr(std::make_unique<data>(std::move(key), std::move(schema)))
    { }
    mutation(partition_key key_, schema_ptr schema)
        : _ptr(std::make_unique<data>(std::move(key_), std::move(schema)))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, const mutation_partition& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), mp))
    { }
    mutation(schema_ptr schema, dht::decorated_key key, mutation_partition&& mp)
        : _ptr(std::make_unique<data>(std::move(schema), std::move(key), std::move(mp)))
    { }
    mutation(const mutation& m)
        : _ptr(std::make_unique<data>(schema_ptr(m.schema()), dht::decorated_key(m.decorated_key()), m.partition()))
    { }

    mutation(mutation&&) = default;
    mutation& operator=(mutation&& x) = default;

    void set_static_cell(const column_definition& def, atomic_cell_or_collection&& value);
    void set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value);
    void set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value);
    void set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {});
    void set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value);
    std::experimental::optional<atomic_cell_or_collection> get_cell(const clustering_key& rkey, const column_definition& def) const;
    const partition_key& key() const { return _ptr->_dk._key; };
    const dht::decorated_key& decorated_key() const { return _ptr->_dk; };
    dht::ring_position ring_position() const { return { decorated_key() }; }
    const dht::token& token() const { return _ptr->_dk._token; }
    const schema_ptr& schema() const { return _ptr->_schema; }
    const mutation_partition& partition() const { return _ptr->_p; }
    mutation_partition& partition() { return _ptr->_p; }
    const utils::UUID& column_family_id() const { return _ptr->_schema->id(); }
    bool operator==(const mutation&) const;
    bool operator!=(const mutation&) const;
public:
    query::result query(const query::partition_slice&, gc_clock::time_point now = gc_clock::now(), uint32_t row_limit = query::max_rows) const;

    // See mutation_partition::live_row_count()
    size_t live_row_count(gc_clock::time_point query_time = gc_clock::time_point::min()) const;
private:
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
    friend class mutation_opt;
};

struct mutation_decorated_key_less_comparator {
    bool operator()(const mutation& m1, const mutation& m2) const;
};

class mutation_opt {
private:
    mutation _mutation;
public:
    mutation_opt() = default;
    mutation_opt(std::experimental::nullopt_t) noexcept { }
    mutation_opt(const mutation& obj) : _mutation(obj) { }
    mutation_opt(mutation&& obj) noexcept : _mutation(std::move(obj)) { }
    mutation_opt(std::experimental::optional<mutation>&& obj) noexcept {
        if (obj) {
            _mutation = std::move(*obj);
        }
    }
    mutation_opt(const mutation_opt&) = default;
    mutation_opt(mutation_opt&&) = default;

    mutation_opt& operator=(std::experimental::nullopt_t) noexcept {
        _mutation = mutation();
        return *this;
    }
    template<typename T>
    std::enable_if_t<std::is_same<std::decay_t<T>, mutation>::value, mutation_opt&>
    operator=(T&& obj) noexcept {
        _mutation = std::forward<T>(obj);
        return *this;
    }
    mutation_opt& operator=(mutation_opt&&) = default;

    explicit operator bool() const noexcept {
        return bool(_mutation._ptr);
    }

    mutation* operator->() noexcept { return &_mutation; }
    const mutation* operator->() const noexcept { return &_mutation; }

    mutation& operator*() noexcept { return _mutation; }
    const mutation& operator*() const noexcept { return _mutation; }

    bool operator==(const mutation_opt& other) const {
        if (!*this && !other) {
            return true;
        }
        if (!*this || !other) {
            return false;
        }
        return _mutation == other._mutation;
    }
    bool operator!=(const mutation_opt& other) const {
        return !(*this == other);
    }
};

inline mutation_opt move_and_disengage(mutation_opt& opt) {
    return std::move(opt);
}

inline
void apply(mutation_opt& dst, mutation&& src) {
    if (!dst) {
        dst = std::move(src);
    } else {
        dst->partition().apply(*src.schema(), src.partition());
    }
}

inline
void apply(mutation_opt& dst, mutation_opt&& src) {
    if (src) {
        apply(dst, std::move(*src));
    }
}

// Returns a range into partitions containing mutations covered by the range.
// partitions must be sorted according to decorated key.
// range must not wrap around.
boost::iterator_range<std::vector<mutation>::const_iterator> slice(
    const std::vector<mutation>& partitions,
    const query::partition_range&);
<|endoftext|>


<commit_before>#include "gum/Anim2SymLoader.h"
#include "gum/FilepathHelper.h"
#include "gum/EasyAnim2Loader.h"
#include "gum/SpineAnim2Loader.h"
#include "gum/SymbolPool.h"
#include "gum/ExtendSymFile.h"

#include <sprite2/Anim2Symbol.h>
#include <simp/NodeAnim2.h>
#include <bimp/typedef.h>

#include <fstream>

#include <string.h>

namespace gum
{

Anim2SymLoader::Anim2SymLoader(s2::Anim2Symbol& sym,
							   const std::shared_ptr<const SymbolLoader>& sym_loader)
	: m_sym(sym)
	, m_sym_loader(sym_loader)
{
}

void Anim2SymLoader::LoadJson(const CU_STR& filepath)
{
	CU_STR dir = FilepathHelper::Dir(filepath);

	Json::Value val;
	Json::Reader reader;
	std::locale::global(std::locale(""));
	std::ifstream fin(filepath.c_str());
	std::locale::global(std::locale("C"));
	reader.parse(fin, val);
	fin.close();

	int type = ExtendSymFile::GetType(val);
	switch (type)
	{
	case SYM_SPINE:
		{
			SpineAnim2Loader loader(m_sym, m_sym_loader);
			loader.LoadJson(val, dir);
		}
		break;
	case SYM_UNKNOWN:
		{
			EasyAnim2Loader loader(m_sym, m_sym_loader);
			loader.LoadJson(val, dir);
		}
		break;
	}
}

static void LoadBinSRT(rg_pose_srt& dst, const simp::NodeAnim2::Srt& src)
{
	dst.trans[0] = src.trans.x;
	dst.trans[1] = src.trans.y;
	dst.rot      = src.rot;
	dst.scale[0] = src.scale.x;
	dst.scale[1] = src.scale.y;
}

void Anim2SymLoader::LoadBin(const simp::NodeAnim2* node)
{
	int sz = CalcNodeSize(node);
	void* buf = malloc(sz);
	uint8_t* ptr = static_cast<uint8_t*>(buf);

	rg_animation* anim = (rg_animation*)ptr;
	anim->max_frame = 0;
	ptr += SIZEOF_RG_ANIM;
	// skeleton
	rg_skeleton* sk = (rg_skeleton*)ptr;
	anim->sk = sk;
	ptr += SIZEOF_RG_SKELETON;
	sk->joint_count = node->joint_count;
	sk->ik_count = node->ik_count;
	sk->root = node->root;
	sk->slot_count = node->slot_count;
	sk->skin_count = node->skin_count;
	//// skins
	m_sym.ClearCachedSym();
	for (int i = 0; i < sk->skin_count; ++i)
	{
		const simp::NodeAnim2::Skin& src = node->skins[i];
		rg_skin* dst = &sk->skins[i];
		dst->type = src.type;
		LoadBinSRT(dst->local, src.local);
		auto sym = SymbolPool::Instance()->Fetch(src.node);
		m_sym.AddCachedSym(sym);
		dst->ud = static_cast<void*>(sym.get());
		ptr += SIZEOF_RG_SKIN;
	}
	//// slots
	sk->slots = (rg_slot*)ptr;
	for (int i = 0; i < sk->slot_count; ++i)
	{
		sk->slots[i].joint = node->slots[i].joint;
		sk->slots[i].skin  = node->slots[i].skin;
	}
	ptr += SIZEOF_RG_SLOT * sk->slot_count;
	//// iks
	sk->iks = (rg_ik*)ptr;
	for (int i = 0; i < sk->ik_count; ++i)
	{
		const simp::NodeAnim2::IK& src = node->iks[i];
		rg_ik* dst = &sk->iks[i];
		dst->joints[0] = src.joints[0];
		dst->joints[1] = src.joints[1];
		dst->target = src.target;
		dst->bend_positive = src.bend_positive;
		dst->length[0] = src.length[0];
		dst->length[1] = src.length[1];
	}
	ptr += SIZEOF_RG_IK * sk->ik_count;
	//// joints
	sk->joints = (rg_joint**)ptr;
	ptr += sizeof(rg_joint*) * sk->joint_count;
	for (int i = 0; i < sk->joint_count; ++i)
	{
		sk->joints[i] = (rg_joint*)ptr;
		ptr += SIZEOF_RG_JOINT;

		const simp::NodeAnim2::Joint& src = node->joints[i];
		rg_joint* dst = sk->joints[i];
		rg_pose_mat_identity(&dst->world_pose);
		LoadBinSRT(dst->local_pose, src.local);
		dst->parent = src.parent;
		dst->children_count = src.chlidren_count;

		ptr += ALIGN_4BYTE(sizeof(uint16_t) * dst->children_count);
	}
	InitJointChildren(sk);
	// timeline
	//// tl joints
	anim->timeline.joints = (rg_tl_joint**)ptr;
	ptr += sizeof(rg_tl_joint*) * sk->joint_count;
	for (int i = 0; i < sk->joint_count; ++i)
	{
		anim->timeline.joints[i] = (rg_tl_joint*)ptr;
		ptr += SIZEOF_RG_TIMELINE_JOINT;

		const simp::NodeAnim2::TL_Joint& src = *node->tl_joints[i];
		rg_tl_joint* dst = anim->timeline.joints[i];
		dst->type = src.type;
		int count = 0;
		for (int j = 0; j < simp::NodeAnim2::DIM_COUNT; ++j) {
			dst->dims_count[j] = src.dims_count[j];
			count += dst->dims_count[j];
		}
		for (int j = 0; j < count; ++j)
		{
			dst->samples[j].time = src.samples[j].time;
			dst->samples[j].lerp = src.samples[j].lerp;
			dst->samples[j].data = src.samples[j].data;
			if (dst->samples[j].time > anim->max_frame) {
				anim->max_frame = dst->samples[j].time;
			}
		}
		ptr += SIZEOF_RG_JOINT_SAMPLE * count;
	}
	//// tl skins
	anim->timeline.skins = (rg_tl_skin**)ptr;
	ptr += sizeof(rg_tl_skin*) * sk->slot_count;
	for (int i = 0; i < sk->slot_count; ++i)
	{
		anim->timeline.skins[i] = (rg_tl_skin*)ptr;
		ptr += SIZEOF_RG_TIMELINE_SKIN;

		const simp::NodeAnim2::TL_Skin& src = *node->tl_skins[i];
		rg_tl_skin* dst = anim->timeline.skins[i];
		dst->skin_count = src.count;
		for (int j = 0; j < dst->skin_count; ++j) {
			dst->skins[j].time = src.samples[j].time;
			dst->skins[j].skin = src.samples[j].skin;
		}

		ptr += SIZEOF_RG_SKIN_SAMPLE * dst->skin_count;
	}
	//// tl deforms
	anim->timeline.deforms = (rg_tl_deform**)ptr;
	ptr += sizeof(rg_tl_deform*) * sk->skin_count;
	for (int i = 0; i < sk->skin_count; ++i)
	{
		anim->timeline.deforms[i] = (rg_tl_deform*)ptr;
		ptr += SIZEOF_RG_TIMELINE_DEFORM;

		const simp::NodeAnim2::TL_Deform& src = *node->tl_deforms[i];
		rg_tl_deform* dst = anim->timeline.deforms[i];
		dst->count = src.count;
		for (int j = 0; j < dst->count; ++j)
		{
			dst->samples[j].time   = src.samples[j]->time;
			dst->samples[j].offset = src.samples[j]->offset;
			dst->samples[j].count  = src.samples[j]->count;
			dst->samples[j].data   = nullptr;
		}
		ptr += SIZEOF_RG_DEFORM_SAMPLE * dst->count;

		for (int j = 0; j < dst->count; ++j)
		{
			if (dst->samples[j].count == 0) {
				dst->samples[j].data = nullptr;
			} else {
				dst->samples[j].data = (float*)ptr;
				int sz = sizeof(float) * 2 * dst->samples[j].count;
				memcpy(dst->samples[j].data, src.samples[j]->vertices, sz);
				ptr += sz;
			}
		}
	}
	m_sym.SetAnim(anim);
}

int Anim2SymLoader::CalcNodeSize(const simp::NodeAnim2* node)
{
	int sz = 0;
	// rg_animation
	sz += SIZEOF_RG_ANIM;
	// rg_skeleton
	sz += SIZEOF_RG_SKELETON;
	// joints
	sz += sizeof(rg_joint*) * node->joint_count;
	for (int i = 0; i < node->joint_count; ++i) {
		sz += SIZEOF_RG_JOINT;
		sz += ALIGN_4BYTE(sizeof(uint16_t) * node->joints[i].chlidren_count);
	}
	// iks
	sz += SIZEOF_RG_IK * node->ik_count;
	// slots
	sz += SIZEOF_RG_SLOT * node->slot_count;
	// skins
	sz += SIZEOF_RG_SKIN * node->skin_count;
	// tl joints
	sz += sizeof(rg_tl_joint*) * node->joint_count;
	for (int i = 0; i < node->joint_count; ++i)
	{
		sz += SIZEOF_RG_TIMELINE_JOINT;
		simp::NodeAnim2::TL_Joint* src = node->tl_joints[i];
		int count = 0;
		for (int j = 0; j < simp::NodeAnim2::DIM_COUNT; ++j) {
			count += src->dims_count[j];
		}
		sz += SIZEOF_RG_JOINT_SAMPLE * count;
	}
	// tl skins
	sz += sizeof(rg_tl_skin*) * node->slot_count;
	for (int i = 0; i < node->slot_count; ++i)
	{
		sz += SIZEOF_RG_TIMELINE_SKIN;
		sz += SIZEOF_RG_SKIN_SAMPLE * node->tl_skins[i]->count;
	}
	// tl deforms
	sz += sizeof(rg_tl_deform*) * node->skin_count;
	for (int i = 0; i < node->skin_count; ++i)
	{
		sz += SIZEOF_RG_TIMELINE_DEFORM;
		for (int j = 0; j < node->tl_deforms[i]->count; ++j) {
			sz += SIZEOF_RG_DEFORM_SAMPLE;
 			sz += sizeof(float) * 2 * node->tl_deforms[i]->samples[j]->count;
		}
	}
	return sz;
}

void Anim2SymLoader::InitJointChildren(rg_skeleton* sk)
{
	CU_VEC<int> node_tag;
	node_tag.resize(sk->joint_count, 0);
	for (int i = 0; i < sk->joint_count; ++i) {
		int parent = sk->joints[i]->parent;
		if (parent != RG_JOINT_UNKNOWN) {
			sk->joints[parent]->children[node_tag[parent]++] = i;
		}
	}
}

}<commit_msg>[ADDED] load anim2 's curve<commit_after>#include "gum/Anim2SymLoader.h"
#include "gum/FilepathHelper.h"
#include "gum/EasyAnim2Loader.h"
#include "gum/SpineAnim2Loader.h"
#include "gum/SymbolPool.h"
#include "gum/ExtendSymFile.h"

#include <sprite2/Anim2Symbol.h>
#include <simp/NodeAnim2.h>
#include <bimp/typedef.h>

#include <fstream>

#include <string.h>
#include <assert.h>

namespace gum
{

Anim2SymLoader::Anim2SymLoader(s2::Anim2Symbol& sym,
							   const std::shared_ptr<const SymbolLoader>& sym_loader)
	: m_sym(sym)
	, m_sym_loader(sym_loader)
{
}

void Anim2SymLoader::LoadJson(const CU_STR& filepath)
{
	CU_STR dir = FilepathHelper::Dir(filepath);

	Json::Value val;
	Json::Reader reader;
	std::locale::global(std::locale(""));
	std::ifstream fin(filepath.c_str());
	std::locale::global(std::locale("C"));
	reader.parse(fin, val);
	fin.close();

	int type = ExtendSymFile::GetType(val);
	switch (type)
	{
	case SYM_SPINE:
		{
			SpineAnim2Loader loader(m_sym, m_sym_loader);
			loader.LoadJson(val, dir);
		}
		break;
	case SYM_UNKNOWN:
		{
			EasyAnim2Loader loader(m_sym, m_sym_loader);
			loader.LoadJson(val, dir);
		}
		break;
	}
}

static void LoadBinSRT(rg_pose_srt& dst, const simp::NodeAnim2::Srt& src)
{
	dst.trans[0] = src.trans.x;
	dst.trans[1] = src.trans.y;
	dst.rot      = src.rot;
	dst.scale[0] = src.scale.x;
	dst.scale[1] = src.scale.y;
}

void Anim2SymLoader::LoadBin(const simp::NodeAnim2* node)
{
	int sz = CalcNodeSize(node);
	void* buf = malloc(sz);
	uint8_t* ptr = static_cast<uint8_t*>(buf);

	rg_animation* anim = (rg_animation*)ptr;
	anim->max_frame = 0;
	ptr += SIZEOF_RG_ANIM;
	// skeleton
	rg_skeleton* sk = (rg_skeleton*)ptr;
	anim->sk = sk;
	ptr += SIZEOF_RG_SKELETON;
	sk->joint_count = node->joint_count;
	sk->ik_count = node->ik_count;
	sk->root = node->root;
	sk->slot_count = node->slot_count;
	sk->skin_count = node->skin_count;
	//// skins
	m_sym.ClearCachedSym();
	for (int i = 0; i < sk->skin_count; ++i)
	{
		const simp::NodeAnim2::Skin& src = node->skins[i];
		rg_skin* dst = &sk->skins[i];
		dst->type = src.type;
		LoadBinSRT(dst->local, src.local);
		auto sym = SymbolPool::Instance()->Fetch(src.node);
		m_sym.AddCachedSym(sym);
		dst->ud = static_cast<void*>(sym.get());
		ptr += SIZEOF_RG_SKIN;
	}
	//// slots
	sk->slots = (rg_slot*)ptr;
	for (int i = 0; i < sk->slot_count; ++i)
	{
		sk->slots[i].joint = node->slots[i].joint;
		sk->slots[i].skin  = node->slots[i].skin;
	}
	ptr += SIZEOF_RG_SLOT * sk->slot_count;
	//// iks
	sk->iks = (rg_ik*)ptr;
	for (int i = 0; i < sk->ik_count; ++i)
	{
		const simp::NodeAnim2::IK& src = node->iks[i];
		rg_ik* dst = &sk->iks[i];
		dst->joints[0] = src.joints[0];
		dst->joints[1] = src.joints[1];
		dst->target = src.target;
		dst->bend_positive = src.bend_positive;
		dst->length[0] = src.length[0];
		dst->length[1] = src.length[1];
	}
	ptr += SIZEOF_RG_IK * sk->ik_count;
	//// joints
	sk->joints = (rg_joint**)ptr;
	ptr += sizeof(rg_joint*) * sk->joint_count;
	for (int i = 0; i < sk->joint_count; ++i)
	{
		sk->joints[i] = (rg_joint*)ptr;
		ptr += SIZEOF_RG_JOINT;

		const simp::NodeAnim2::Joint& src = node->joints[i];
		rg_joint* dst = sk->joints[i];
		rg_pose_mat_identity(&dst->world_pose);
		LoadBinSRT(dst->local_pose, src.local);
		dst->parent = src.parent;
		dst->children_count = src.chlidren_count;

		ptr += ALIGN_4BYTE(sizeof(uint16_t) * dst->children_count);
	}
	InitJointChildren(sk);
	// timeline
	//// tl joints
	anim->timeline.joints = (rg_tl_joint**)ptr;
	ptr += sizeof(rg_tl_joint*) * sk->joint_count;
	for (int i = 0; i < sk->joint_count; ++i)
	{
		anim->timeline.joints[i] = (rg_tl_joint*)ptr;
		ptr += SIZEOF_RG_TIMELINE_JOINT;

		const simp::NodeAnim2::TL_Joint& src = *node->tl_joints[i];
		rg_tl_joint* dst = anim->timeline.joints[i];
		dst->type = src.type;
		int count = 0;
		for (int j = 0; j < simp::NodeAnim2::DIM_COUNT; ++j) {
			dst->dims_count[j] = src.dims_count[j];
			count += dst->dims_count[j];
		}
		for (int j = 0; j < count; ++j)
		{
			dst->samples[j].time  = src.samples[j].time;
			dst->samples[j].lerp  = src.samples[j].lerp;
			dst->samples[j].curve = src.samples[j].curve;
			dst->samples[j].data  = src.samples[j].data;
			if (dst->samples[j].time > anim->max_frame) {
				anim->max_frame = dst->samples[j].time;
			}
		}
		ptr += SIZEOF_RG_JOINT_SAMPLE * count;
	}
	//// tl skins
	anim->timeline.skins = (rg_tl_skin**)ptr;
	ptr += sizeof(rg_tl_skin*) * sk->slot_count;
	for (int i = 0; i < sk->slot_count; ++i)
	{
		anim->timeline.skins[i] = (rg_tl_skin*)ptr;
		ptr += SIZEOF_RG_TIMELINE_SKIN;

		const simp::NodeAnim2::TL_Skin& src = *node->tl_skins[i];
		rg_tl_skin* dst = anim->timeline.skins[i];
		dst->skin_count = src.count;
		for (int j = 0; j < dst->skin_count; ++j) {
			dst->skins[j].time = src.samples[j].time;
			dst->skins[j].skin = src.samples[j].skin;
		}

		ptr += SIZEOF_RG_SKIN_SAMPLE * dst->skin_count;
	}
	//// tl deforms
	anim->timeline.deforms = (rg_tl_deform**)ptr;
	ptr += sizeof(rg_tl_deform*) * sk->skin_count;
	for (int i = 0; i < sk->skin_count; ++i)
	{
		anim->timeline.deforms[i] = (rg_tl_deform*)ptr;
		ptr += SIZEOF_RG_TIMELINE_DEFORM;

		const simp::NodeAnim2::TL_Deform& src = *node->tl_deforms[i];
		rg_tl_deform* dst = anim->timeline.deforms[i];
		dst->count = src.count;
		for (int j = 0; j < dst->count; ++j)
		{
			dst->samples[j].time   = src.samples[j]->time;
			dst->samples[j].offset = src.samples[j]->offset;
			dst->samples[j].curve  = src.samples[j]->curve;
			dst->samples[j].count  = src.samples[j]->count;
			dst->samples[j].data   = nullptr;
		}
		ptr += SIZEOF_RG_DEFORM_SAMPLE * dst->count;

		for (int j = 0; j < dst->count; ++j)
		{
			if (dst->samples[j].count == 0) {
				dst->samples[j].data = nullptr;
			} else {
				dst->samples[j].data = (float*)ptr;
				int sz = sizeof(float) * 2 * dst->samples[j].count;
				memcpy(dst->samples[j].data, src.samples[j]->vertices, sz);
				ptr += sz;
			}
		}
	}
	//// curves
	anim->curve_count = node->curve_count;
	anim->curves = (rg_curve**)ptr;
	ptr += sizeof(rg_curve*) * anim->curve_count;
	for (int i = 0; i < anim->curve_count; ++i)
	{
		anim->curves[i] = (rg_curve*)ptr;
		ptr += SIZEOF_RG_CURVE;

		auto& src = node->curves[i];
		auto& dst = anim->curves[i];
		dst->x0 = src.x0;
		dst->y0 = src.y0;
		dst->x1 = src.x1;
		dst->y1 = src.y1;
	}
	assert(ptr - buf == sz);
	m_sym.SetAnim(anim);
}

int Anim2SymLoader::CalcNodeSize(const simp::NodeAnim2* node)
{
	int sz = 0;
	// rg_animation
	sz += SIZEOF_RG_ANIM;
	// rg_skeleton
	sz += SIZEOF_RG_SKELETON;
	// joints
	sz += sizeof(rg_joint*) * node->joint_count;
	for (int i = 0; i < node->joint_count; ++i) {
		sz += SIZEOF_RG_JOINT;
		sz += ALIGN_4BYTE(sizeof(uint16_t) * node->joints[i].chlidren_count);
	}
	// iks
	sz += SIZEOF_RG_IK * node->ik_count;
	// slots
	sz += SIZEOF_RG_SLOT * node->slot_count;
	// skins
	sz += SIZEOF_RG_SKIN * node->skin_count;
	// tl joints
	sz += sizeof(rg_tl_joint*) * node->joint_count;
	for (int i = 0; i < node->joint_count; ++i)
	{
		sz += SIZEOF_RG_TIMELINE_JOINT;
		simp::NodeAnim2::TL_Joint* src = node->tl_joints[i];
		int count = 0;
		for (int j = 0; j < simp::NodeAnim2::DIM_COUNT; ++j) {
			count += src->dims_count[j];
		}
		sz += SIZEOF_RG_JOINT_SAMPLE * count;
	}
	// tl skins
	sz += sizeof(rg_tl_skin*) * node->slot_count;
	for (int i = 0; i < node->slot_count; ++i)
	{
		sz += SIZEOF_RG_TIMELINE_SKIN;
		sz += SIZEOF_RG_SKIN_SAMPLE * node->tl_skins[i]->count;
	}
	// tl deforms
	sz += sizeof(rg_tl_deform*) * node->skin_count;
	for (int i = 0; i < node->skin_count; ++i)
	{
		sz += SIZEOF_RG_TIMELINE_DEFORM;
		for (int j = 0; j < node->tl_deforms[i]->count; ++j) {
			sz += SIZEOF_RG_DEFORM_SAMPLE;
 			sz += sizeof(float) * 2 * node->tl_deforms[i]->samples[j]->count;
		}
	}
	// curves
	sz += sizeof(rg_curve*) * node->curve_count;
	sz += SIZEOF_RG_CURVE * node->curve_count;
	return sz;
}

void Anim2SymLoader::InitJointChildren(rg_skeleton* sk)
{
	CU_VEC<int> node_tag;
	node_tag.resize(sk->joint_count, 0);
	for (int i = 0; i < sk->joint_count; ++i) {
		int parent = sk->joints[i]->parent;
		if (parent != RG_JOINT_UNKNOWN) {
			sk->joints[parent]->children[node_tag[parent]++] = i;
		}
	}
}

}<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include "elements.h"

using namespace std;
/**
  * @elementspage The Gaussian Optimization Analytical Tool (GOAT)
  *
  * Welcome to the Gaussian Optimization Analytical Tool (GOAT) documentation site!
  * Users may find relevant info related to this program, a program designed to provide
  * structural analyses of biomolecules successfully optimized using Gaussian software.
  *
  * @short elements program
  * @file elements.cpp
  * @author Hananh Lozano
  * @param none
  * @return
  *
  * The purpose of this program is to identify the first eighteen elements, hydrogen to argon, and assign them a number starting with 1. Then it will take the enum and string files and build upon those to determine how many bonds between atoms there will be.**/

enum elements_hydrogen_to_argon {
    HYDROGEN = 1,
    HELIUM,
    LITHIUM,
    BERLLYIUM,
    BORON,
    CARBON,
    NITROGEN,
    OXYGEN,
    FLUORINE,
    NEON,
    SODIUM,
    MAGNESIUM,
    ALUMINUM,
    SILICON,
    PHOSPHOROUS,
    SULFUR,
    CHLORINE,
    ARGON,

    };

    elements_hydrogen_to_argon element;

    string elements_to_string (elements_hydrogen_to_argon d) {
     if (element == HYDROGEN   ) return "Hydrogen";
     if (element == HELIUM     ) return "Helium";
     if (element == LITHIUM    ) return "Lithium";
     if (element == BERLLYIUM  ) return "Beryllium";
     if (element == BORON      ) return "Boron";
     if (element == CARBON     ) return "Carbon";
     if (element == NITROGEN   ) return "Nitrogen";
     if (element == OXYGEN     ) return "Oxygen";
     if (element == FLUORINE   ) return "Fluorine";
     if (element == NEON       ) return "Neon";
     if (element == SODIUM     ) return "Sodium";
     if (element == MAGNESIUM  ) return "Magnesium";
     if (element == ALUMINUM   ) return "Aluminum";
     if (element == SILICON    ) return "Silicon";
     if (element == PHOSPHOROUS) return "Phosphorous";
     if (element == SULFUR     ) return "Sulfur";
     if (element == CHLORINE   ) return "Chlorine";
     if (element == ARGON      ) return "Argon";

    };

    //access coordinates.csv file array/struct
    //read .csv array file

int main() {

   if Hydrogen, Lithium, or Sodium return "1 bond H,Li,Na";
   if Beryllium or Magnesium return "2 bonds Be,Mg";
   if Boron or Aluminum return "3 bonds B,Al";
   if Carbon or Silicon return "4 bonds C,Si";
   if Nitrogen or Phosphorous return "3 bonds N,P";
   if Oxygen or Sulfur return "2 bonds O,S";
   if Fluorine or Chlorine return "1 bond F, Cl";
   if Helium, Neon, or Argon return "0 bonds He,Ne,Ar";
   }

return null;
}
<commit_msg>added Doxygen documentation header<commit_after>#include <iostream>
#include <string>

#include "elements.h"

using namespace std;
/**
  * @file elements.cpp
  * @author Hananh Lozano
  * @param none
  * @return 0 if success
  *
  * The purpose of this program is to identify the first eighteen elements,
  * hydrogen to argon, and assign them a number starting with 1. Then it will
  * take the enum and string files and build upon those to determine how many      * bonds between atoms there will be.
  **/

enum elements_hydrogen_to_argon {
    HYDROGEN = 1,
    HELIUM,
    LITHIUM,
    BERLLYIUM,
    BORON,
    CARBON,
    NITROGEN,
    OXYGEN,
    FLUORINE,
    NEON,
    SODIUM,
    MAGNESIUM,
    ALUMINUM,
    SILICON,
    PHOSPHOROUS,
    SULFUR,
    CHLORINE,
    ARGON,

    };

    elements_hydrogen_to_argon element;

    string elements_to_string (elements_hydrogen_to_argon d) {
     if (element == HYDROGEN   ) return "Hydrogen";
     if (element == HELIUM     ) return "Helium";
     if (element == LITHIUM    ) return "Lithium";
     if (element == BERLLYIUM  ) return "Beryllium";
     if (element == BORON      ) return "Boron";
     if (element == CARBON     ) return "Carbon";
     if (element == NITROGEN   ) return "Nitrogen";
     if (element == OXYGEN     ) return "Oxygen";
     if (element == FLUORINE   ) return "Fluorine";
     if (element == NEON       ) return "Neon";
     if (element == SODIUM     ) return "Sodium";
     if (element == MAGNESIUM  ) return "Magnesium";
     if (element == ALUMINUM   ) return "Aluminum";
     if (element == SILICON    ) return "Silicon";
     if (element == PHOSPHOROUS) return "Phosphorous";
     if (element == SULFUR     ) return "Sulfur";
     if (element == CHLORINE   ) return "Chlorine";
     if (element == ARGON      ) return "Argon";

    };

    //access coordinates.csv file array/struct
    //read .csv array file

int main() {

   if Hydrogen, Lithium, or Sodium return "1 bond H,Li,Na";
   if Beryllium or Magnesium return "2 bonds Be,Mg";
   if Boron or Aluminum return "3 bonds B,Al";
   if Carbon or Silicon return "4 bonds C,Si";
   if Nitrogen or Phosphorous return "3 bonds N,P";
   if Oxygen or Sulfur return "2 bonds O,S";
   if Fluorine or Chlorine return "1 bond F, Cl";
   if Helium, Neon, or Argon return "0 bonds He,Ne,Ar";
   }

return null;
}
<|endoftext|>


<commit_before>/** \file test_csv_convert.cpp
 * Executable to convert dictionary CSV file from source pattern to destination pattern, which conversion rule is defined in a configuration file, such as "csv-convert-ipa-juman-eucjp.def".
 * Below is the usage examples:
 * \code
 * The encoding type of those CSV files in source directory is predefined by the "dictionary-charset" entry of "dicrc" file.
 * While the encoding type of binary files in destination directory could be set to "eucjp", "sjis" or "utf8" like below, which is "eucjp" defaultly.
 * $ ./jma_csv_convert --config ../db/config/csv-convert-ipa-juman-eucjp.def --output ipa_proper.csv ../db/ipadic/src/Noun.proper.csv ../db/ipadic/src/Noun.name.csv ../db/ipadic/src/Noun.org.csv ../db/ipadic/src/Noun.place.csv
 * \endcode
 *
 * \author Jun Jiang
 * \version 0.1
 * \date Sep 18, 2009
 */

#include "dictionary_rewriter.h"
#include "utils.h"
#include "common.h"

#include <iostream>
#include <fstream>
#include <cassert>
#include <cstdlib>
#include <cstring>

using namespace std;
using namespace MeCab;

namespace
{
/**
 * Print the test usage.
 */
void printUsage()
{
    cerr << "Usage: ./jma_csv_convert --config DEF_FILE --output DEST_FILE SOURCE_CSV..." << endl;
}

/**
 * Check whether the command \e option matches the \e name.
 * \param str the command option string given by user.
 * \param option the standard option name.
 * \attention if the match is failed, print out the command usage information, and terminate the whole pragram.
 */
void checkOptionName(const char* str, const char* option)
{
    if(strcmp(str, option) != 0)
    {
        cerr << "unknown command option " << str << ", which should be " << option << endl;
        printUsage();
        exit(1);
    }
}

/**
 * Append the rule in string \e str to the rule vector \e r.
 * \param r the rule vector.
 * \param str the rule string consisting of source and destination pattern.
 */
void append_rewrite_rule(RewriteRules *r, char* str)
{
    char *col[3];
    const size_t n = tokenize2(str, " \t", col, 3);
    CHECK_DIE(n >= 2) << "format error: " << str;
    r->resize(r->size() + 1);
    string tmp;
    if (n >= 3) {
        tmp = col[1];
        tmp += ' ';
        tmp += col[2];
        col[1] = const_cast<char *>(tmp.c_str());
    }
    r->back().set_pattern(col[0], col[1]);
}

/**
 * Rewrite dictionary CSV file.
 */
class CSVRewriter
{
private:
    /** rules consisting of source and destination pattern */
    RewriteRules rules_;

public:
    /**
     * Open configuration file, which defines the source and destination patterns.
     * \param fileName configuration file name
     * \return true for success, false for failure.
     */
    bool open(const char* fileName);

    /**
     * Rewrite the string \e src to \e dest, basing on the patterns in configuration file by \e open().
     * \param src source string to convert from
     * \param dest destination string as output
     * \return true for success, false for failure.
     */
    bool rewrite(const string& src, string& dest) const;
};

bool CSVRewriter::open(const char* fileName)
{
    ifstream ifs(fileName);
    if(! ifs)
    {
        cerr << "fail to open CSVRewriter configuration file: " << fileName << endl;
        return false;
    }

    string line;
    while(getline(ifs, line))
    {
        if(line.empty() || line[0] == '#')
        {
            continue;
        }

        char* str = const_cast<char*>(line.c_str());
        append_rewrite_rule(&rules_, str);
    }

    return true;
}

bool CSVRewriter::rewrite(const string& src, string& dest) const
{
    char buf[BUF_SIZE];
    char *col[BUF_SIZE];
    CHECK_DIE(src.size() < sizeof(buf) - 1) << "too many characters in CSV entry";
    strncpy(buf, src.c_str(), sizeof(buf) - 1);
    size_t n = tokenizeCSV(buf, col, sizeof(col));
    CHECK_DIE(n < sizeof(col)) << "too many columns in CSV entry";
    return rules_.rewrite(n, const_cast<const char **>(col), &dest);
}

}

/**
 * Main function.
 */
int main(int argc, char* argv[])
{
    if(argc < 6)
    {
        printUsage();
        exit(1);
    }

    checkOptionName(argv[1], "--config");
    checkOptionName(argv[3], "--output");

    const char* configFile = argv[2];
    cout << "config file: " << configFile << endl;

    // CSV file rewriter
    CSVRewriter rewriter;
    if(! rewriter.open(configFile))
    {
        cerr << "fail to open config file: " << configFile << endl;
        exit(1);
    }

    const char* destFile = argv[4];
    ofstream to(destFile);
    if(! to)
    {
        cerr << "failed to create file " << destFile << endl;
        exit(1);
    }

    unsigned int count = 0;
    unsigned int ignore = 0;
    for(int i=5; i<argc; ++i)
    {
        const char* sourceFile = argv[i];
        cout << "converting source file: " << sourceFile << endl;

        ifstream from(sourceFile);
        if(! from)
        {
            cerr << "failed to open source file: " << sourceFile << endl;
            exit(1);
        }

        string line, dest;
        while(getline(from, line))
        {
            if(line.empty())
                continue;

            if(! rewriter.rewrite(line, dest))
            {
                cerr << "as no pattern is matched, ignoring line: " << line << endl;
                ++ignore;
                continue;
            }

            to << dest << endl;
            ++count;
        }
    }

    cout << "succeeded output to " << destFile << endl;
    cout << "total ignored entries: " << ignore << endl;
    cout << "total converted entries: " << count << endl;
    return 0;
}
<commit_msg>add common nouns from IPA to Juman dictionary.<commit_after>/** \file test_csv_convert.cpp
 * Executable to convert dictionary CSV file from source pattern to destination pattern, which conversion rule is defined in a configuration file, such as "csv-convert-ipa-juman-eucjp.def".
 * Below is the usage examples:
 * \code
 * The configuration file defining conversion rules is "../db/config/csv-convert-ipa-juman-eucjp.def",
 * the source CSV files are "Noun.proper.csv", "Noun.name.csv", "Noun.org.csv" and "Noun.place.csv" in IPA dictionary,
 * the destination CSV file is "ipa_proper_noun.csv".
 * $ ./jma_csv_convert --config ../db/config/csv-convert-ipa-juman-eucjp.def --output ipa_proper_noun.csv ../db/ipadic/src/Noun.proper.csv ../db/ipadic/src/Noun.name.csv ../db/ipadic/src/Noun.org.csv ../db/ipadic/src/Noun.place.csv
 * \endcode
 *
 * \author Jun Jiang
 * \version 0.1
 * \date Sep 18, 2009
 */

#include "dictionary_rewriter.h"
#include "utils.h"
#include "common.h"

#include <iostream>
#include <fstream>
#include <cassert>
#include <cstdlib>
#include <cstring>

using namespace std;
using namespace MeCab;

namespace
{
/**
 * Print the test usage.
 */
void printUsage()
{
    cerr << "Usage: ./jma_csv_convert --config DEF_FILE --output DEST_FILE SOURCE_CSV..." << endl;
}

/**
 * Check whether the command \e option matches the \e name.
 * \param str the command option string given by user.
 * \param option the standard option name.
 * \attention if the match is failed, print out the command usage information, and terminate the whole pragram.
 */
void checkOptionName(const char* str, const char* option)
{
    if(strcmp(str, option) != 0)
    {
        cerr << "unknown command option " << str << ", which should be " << option << endl;
        printUsage();
        exit(1);
    }
}

/**
 * Append the rule in string \e str to the rule vector \e r.
 * \param r the rule vector.
 * \param str the rule string consisting of source and destination pattern.
 */
void append_rewrite_rule(RewriteRules *r, char* str)
{
    char *col[3];
    const size_t n = tokenize2(str, " \t", col, 3);
    CHECK_DIE(n >= 2) << "format error: " << str;
    r->resize(r->size() + 1);
    string tmp;
    if (n >= 3) {
        tmp = col[1];
        tmp += ' ';
        tmp += col[2];
        col[1] = const_cast<char *>(tmp.c_str());
    }
    r->back().set_pattern(col[0], col[1]);
}

/**
 * Rewrite dictionary CSV file.
 */
class CSVRewriter
{
private:
    /** rules consisting of source and destination pattern */
    RewriteRules rules_;

public:
    /**
     * Open configuration file, which defines the source and destination patterns.
     * \param fileName configuration file name
     * \return true for success, false for failure.
     */
    bool open(const char* fileName);

    /**
     * Rewrite the string \e src to \e dest, basing on the patterns in configuration file by \e open().
     * \param src source string to convert from
     * \param dest destination string as output
     * \return true for success, false for failure.
     */
    bool rewrite(const string& src, string& dest) const;
};

bool CSVRewriter::open(const char* fileName)
{
    ifstream ifs(fileName);
    if(! ifs)
    {
        cerr << "fail to open CSVRewriter configuration file: " << fileName << endl;
        return false;
    }

    string line;
    while(getline(ifs, line))
    {
        if(line.empty() || line[0] == '#')
        {
            continue;
        }

        char* str = const_cast<char*>(line.c_str());
        append_rewrite_rule(&rules_, str);
    }

    return true;
}

bool CSVRewriter::rewrite(const string& src, string& dest) const
{
    char buf[BUF_SIZE];
    char *col[BUF_SIZE];
    CHECK_DIE(src.size() < sizeof(buf) - 1) << "too many characters in CSV entry";
    strncpy(buf, src.c_str(), sizeof(buf) - 1);
    size_t n = tokenizeCSV(buf, col, sizeof(col));
    CHECK_DIE(n < sizeof(col)) << "too many columns in CSV entry";
    return rules_.rewrite(n, const_cast<const char **>(col), &dest);
}

}

/**
 * Main function.
 */
int main(int argc, char* argv[])
{
    if(argc < 6)
    {
        printUsage();
        exit(1);
    }

    checkOptionName(argv[1], "--config");
    checkOptionName(argv[3], "--output");

    const char* configFile = argv[2];
    cout << "config file: " << configFile << endl;

    // CSV file rewriter
    CSVRewriter rewriter;
    if(! rewriter.open(configFile))
    {
        cerr << "fail to open config file: " << configFile << endl;
        exit(1);
    }

    const char* destFile = argv[4];
    ofstream to(destFile);
    if(! to)
    {
        cerr << "failed to create file " << destFile << endl;
        exit(1);
    }

    unsigned int count = 0;
    unsigned int ignore = 0;
    for(int i=5; i<argc; ++i)
    {
        const char* sourceFile = argv[i];
        cout << "converting source file: " << sourceFile << endl;

        ifstream from(sourceFile);
        if(! from)
        {
            cerr << "failed to open source file: " << sourceFile << endl;
            exit(1);
        }

        string line, dest;
        while(getline(from, line))
        {
            if(line.empty())
                continue;

            if(! rewriter.rewrite(line, dest))
            {
                cerr << "as no pattern is matched, ignoring line: " << line << endl;
                ++ignore;
                continue;
            }

            to << dest << endl;
            ++count;
        }
    }

    cout << "succeeded output to " << destFile << endl;
    cout << "total ignored entries: " << ignore << endl;
    cout << "total converted entries: " << count << endl;
    return 0;
}
<|endoftext|>