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

#include "com_google_ase_Exec.h"

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>

#include "android/log.h"

#define LOG_TAG "Exec"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

static int CreateSubprocess(const char* cmd, const char* arg0, const char* arg1,
                            pid_t* pid) {
  char* devname;
  int ptm = open("/dev/ptmx", O_RDWR);
  if(ptm < 0){
    LOGE("Cannot open /dev/ptmx: %s\n", strerror(errno));
    return -1;
  }
  fcntl(ptm, F_SETFD, FD_CLOEXEC);

  if (grantpt(ptm) || unlockpt(ptm) ||
      ((devname = (char*) ptsname(ptm)) == 0)) {
    LOGE("Trouble with /dev/ptmx: %s\n", strerror(errno));
    return -1;
  }

  *pid = fork();
  if(pid < 0) {
    LOGE("Fork failed: %s\n", strerror(errno));
    return -1;
  }

  if(pid == 0){
    int pts;
    setsid();
    pts = open(devname, O_RDWR);
    if(pts < 0) {
      exit(-1);
    }
    dup2(pts, 0);
    dup2(pts, 1);
    dup2(pts, 2);
    close(ptm);
    execl(cmd, cmd, arg0, arg1, NULL);
    exit(-1);
  } else {
    return ptm;
  }
}

void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
  jclass clazz = env->FindClass(name);
  if (clazz != NULL) {
    env->ThrowNew(clazz, msg);
  }
  env->DeleteLocalRef(clazz);
}

char* JNU_GetStringNativeChars(JNIEnv* env, jstring jstr) {
  if (jstr == NULL) {
    return NULL;
  }
  jbyteArray bytes = 0;
  jthrowable exc;
  char* result = 0;
  if (env->EnsureLocalCapacity(2) < 0) {
    return 0; /* out of memory error */
  }
  jclass Class_java_lang_String = env->FindClass("java/lang/String");
  jmethodID MID_String_getBytes = env->GetMethodID(
      Class_java_lang_String, "getBytes", "()[B");
  bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes);
  exc = env->ExceptionOccurred();
  if (!exc) {
    jint len = env->GetArrayLength(bytes);
    result = (char*) malloc(len + 1);
    if (result == 0) {
      JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
      env->DeleteLocalRef(bytes);
      return 0;
    }
    env->GetByteArrayRegion(bytes, 0, len, (jbyte*) result);
    result[len] = 0; /* NULL-terminate */
  } else {
    env->DeleteLocalRef(exc);
  }
  env->DeleteLocalRef(bytes);
  return result;
}

int JNU_GetFdFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
  jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor");
  jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor,
                                        "descriptor", "I");
  return env->GetIntField(fileDescriptor, descriptor);
}

JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(
    JNIEnv* env, jclass clazz, jstring cmd, jstring arg0, jstring arg1,
    jintArray processIdArray) {
  char* cmd_native = JNU_GetStringNativeChars(env, cmd);
  char* arg0_native = JNU_GetStringNativeChars(env, arg0);
  char* arg1_native = JNU_GetStringNativeChars(env, arg1);
  pid_t pid;
  int ptm = CreateSubprocess(cmd_native, arg0_native, arg1_native, &pid);
  if (processIdArray) {
    if (env->GetArrayLength(processIdArray) > 0) {
      jboolean isCopy;
      int* proccessId = (int*) env->GetPrimitiveArrayCritical(processIdArray,
                                                              &isCopy);
      if (proccessId) {
        *proccessId = (int) pid;
        env->ReleasePrimitiveArrayCritical(processIdArray, proccessId, 0);
      }
    }
  }

  jclass Class_java_io_FileDescriptor =
      env->FindClass("java/io/FileDescriptor");
  jmethodID init = env->GetMethodID(Class_java_io_FileDescriptor,
                                    "<init>", "()V");
  jobject result = env->NewObject(Class_java_io_FileDescriptor, init);

  if (!result) {
    LOGE("Couldn't create a FileDescriptor.");
  } else {
    jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor,
                                        "descriptor", "I");
    env->SetIntField(result, descriptor, ptm);
  }
  return result;
}

JNIEXPORT void Java_com_google_ase_Exec_setPtyWindowSize(
    JNIEnv* env, jclass clazz, jobject fileDescriptor, jint row, jint col,
    jint xpixel, jint ypixel) {
  struct winsize sz;
  int fd = JNU_GetFdFromFileDescriptor(env, fileDescriptor);
  if (env->ExceptionOccurred() != NULL) {
    return;
  }
  sz.ws_row = row;
  sz.ws_col = col;
  sz.ws_xpixel = xpixel;
  sz.ws_ypixel = ypixel;
  ioctl(fd, TIOCSWINSZ, &sz);
}

JNIEXPORT jint Java_com_google_ase_Exec_waitFor(JNIEnv* env, jclass clazz,
                                                jint procId) {
  int status;
  waitpid(procId, &status, 0);
  int result = 0;
  if (WIFEXITED(status)) {
    result = WEXITSTATUS(status);
  }
  return result;
}
<commit_msg>Fixed pointer bug.<commit_after>/*
 * Copyright (C) 2007 The Android Open Source Project
 * Copyright (C) 2009 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "com_google_ase_Exec.h"

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>

#include "android/log.h"

#define LOG_TAG "Exec"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

static int CreateSubprocess(const char* cmd, const char* arg0, const char* arg1,
                            pid_t* pid) {
  char* devname;
  int ptm = open("/dev/ptmx", O_RDWR);
  if(ptm < 0){
    LOGE("Cannot open /dev/ptmx: %s\n", strerror(errno));
    return -1;
  }
  fcntl(ptm, F_SETFD, FD_CLOEXEC);

  if (grantpt(ptm) || unlockpt(ptm) ||
      ((devname = (char*) ptsname(ptm)) == 0)) {
    LOGE("Trouble with /dev/ptmx: %s\n", strerror(errno));
    return -1;
  }

  *pid = fork();
  if(*pid < 0) {
    LOGE("Fork failed: %s\n", strerror(errno));
    return -1;
  }

  if(*pid == 0){
    int pts;
    setsid();
    pts = open(devname, O_RDWR);
    if(pts < 0) {
      exit(-1);
    }
    dup2(pts, 0);
    dup2(pts, 1);
    dup2(pts, 2);
    close(ptm);
    execl(cmd, cmd, arg0, arg1, NULL);
    exit(-1);
  } else {
    return ptm;
  }
}

void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
  jclass clazz = env->FindClass(name);
  if (clazz != NULL) {
    env->ThrowNew(clazz, msg);
  }
  env->DeleteLocalRef(clazz);
}

char* JNU_GetStringNativeChars(JNIEnv* env, jstring jstr) {
  if (jstr == NULL) {
    return NULL;
  }
  jbyteArray bytes = 0;
  jthrowable exc;
  char* result = 0;
  if (env->EnsureLocalCapacity(2) < 0) {
    return 0; /* out of memory error */
  }
  jclass Class_java_lang_String = env->FindClass("java/lang/String");
  jmethodID MID_String_getBytes = env->GetMethodID(
      Class_java_lang_String, "getBytes", "()[B");
  bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes);
  exc = env->ExceptionOccurred();
  if (!exc) {
    jint len = env->GetArrayLength(bytes);
    result = (char*) malloc(len + 1);
    if (result == 0) {
      JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
      env->DeleteLocalRef(bytes);
      return 0;
    }
    env->GetByteArrayRegion(bytes, 0, len, (jbyte*) result);
    result[len] = 0; /* NULL-terminate */
  } else {
    env->DeleteLocalRef(exc);
  }
  env->DeleteLocalRef(bytes);
  return result;
}

int JNU_GetFdFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
  jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor");
  jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor,
                                        "descriptor", "I");
  return env->GetIntField(fileDescriptor, descriptor);
}

JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(
    JNIEnv* env, jclass clazz, jstring cmd, jstring arg0, jstring arg1,
    jintArray processIdArray) {
  char* cmd_native = JNU_GetStringNativeChars(env, cmd);
  char* arg0_native = JNU_GetStringNativeChars(env, arg0);
  char* arg1_native = JNU_GetStringNativeChars(env, arg1);
  pid_t pid;
  int ptm = CreateSubprocess(cmd_native, arg0_native, arg1_native, &pid);
  if (processIdArray) {
    if (env->GetArrayLength(processIdArray) > 0) {
      jboolean isCopy;
      int* proccessId = (int*) env->GetPrimitiveArrayCritical(processIdArray,
                                                              &isCopy);
      if (proccessId) {
        *proccessId = (int) pid;
        env->ReleasePrimitiveArrayCritical(processIdArray, proccessId, 0);
      }
    }
  }

  jclass Class_java_io_FileDescriptor =
      env->FindClass("java/io/FileDescriptor");
  jmethodID init = env->GetMethodID(Class_java_io_FileDescriptor,
                                    "<init>", "()V");
  jobject result = env->NewObject(Class_java_io_FileDescriptor, init);

  if (!result) {
    LOGE("Couldn't create a FileDescriptor.");
  } else {
    jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor,
                                        "descriptor", "I");
    env->SetIntField(result, descriptor, ptm);
  }
  return result;
}

JNIEXPORT void Java_com_google_ase_Exec_setPtyWindowSize(
    JNIEnv* env, jclass clazz, jobject fileDescriptor, jint row, jint col,
    jint xpixel, jint ypixel) {
  struct winsize sz;
  int fd = JNU_GetFdFromFileDescriptor(env, fileDescriptor);
  if (env->ExceptionOccurred() != NULL) {
    return;
  }
  sz.ws_row = row;
  sz.ws_col = col;
  sz.ws_xpixel = xpixel;
  sz.ws_ypixel = ypixel;
  ioctl(fd, TIOCSWINSZ, &sz);
}

JNIEXPORT jint Java_com_google_ase_Exec_waitFor(JNIEnv* env, jclass clazz,
                                                jint procId) {
  int status;
  waitpid(procId, &status, 0);
  int result = 0;
  if (WIFEXITED(status)) {
    result = WEXITSTATUS(status);
  }
  return result;
}
<|endoftext|>


<commit_before>#ifndef EXECUTORS_H
#define EXECUTORS_H

#include "processes.hpp"
#include "reader.hpp" // for Bytecode classes

/*
  hl functions are represented by a Closure structure, which has an
  attached bytecode_t array.

  Calling convention:

  proc.stack[0] *must* be a Closure

  proc.stack[0] contains the closure.  If it is a "normal"
  function, proc.stack[1] is the "continuation" function
  and proc.stack[2..n] are the parameters.
  proc.stack.size() is the number of parameters including
  the function itself and the continuation.

  If it is a "continuation" function, proc.stack[1] is always
  the return value. proc.stack.size() will be 2.

  Functions never return.
*/

#define PASTE_SYMBOLS(x,y) x##y

/*
  Not necessary when using GCC.
  NOTE!  We retain this and even add references to
  an _e_bytecode_label type so that modders who
  happen to use *only* GCC will remember to update
  the declarations for the benefit of non-GCC
  users.
*/

#define DECLARE_BYTECODES enum _e_bytecode_label {
#define BYTECODE_ENUM(x) PASTE_SYMBOLS(_bytecode_, x)
#define A_BYTECODE(x) BYTECODE_ENUM(x),
#define END_DECLARE_BYTECODES __null_bytecode };
DECLARE_BYTECODES
	A_BYTECODE(apply)
	A_BYTECODE(apply_invert_k)
	A_BYTECODE(apply_list)
	A_BYTECODE(apply_k_release)
	A_BYTECODE(car)
	A_BYTECODE(car_local_push)
	A_BYTECODE(car_clos_push)
	A_BYTECODE(cdr)
	A_BYTECODE(cdr_local_push)
	A_BYTECODE(cdr_clos_push)
	A_BYTECODE(check_vars)
	A_BYTECODE(closure)
	A_BYTECODE(closure_ref)
	A_BYTECODE(composeo)
	A_BYTECODE(cons)
	A_BYTECODE(b_continue)
	A_BYTECODE(continue_local)
	A_BYTECODE(continue_on_clos)
	A_BYTECODE(global)
	A_BYTECODE(global_set)
	A_BYTECODE(halt)
	A_BYTECODE(halt_local_push)
	A_BYTECODE(halt_clos_push)
	A_BYTECODE(b_if)
	A_BYTECODE(if_local)
	A_BYTECODE(b_int)
	A_BYTECODE(k_closure)
	A_BYTECODE(k_closure_recreate)
	A_BYTECODE(k_closure_reuse)
	A_BYTECODE(lit_nil)
	A_BYTECODE(lit_t)
	A_BYTECODE(local)
	A_BYTECODE(reducto)
	A_BYTECODE(rep)
	A_BYTECODE(rep_local_push)
	A_BYTECODE(rep_clos_push)
	A_BYTECODE(sv)
	A_BYTECODE(sv_local_push)
	A_BYTECODE(sv_clos_push)
	A_BYTECODE(sv_ref)
	A_BYTECODE(sv_ref_local_push)
	A_BYTECODE(sv_ref_clos_push)
	A_BYTECODE(sv_set)
	A_BYTECODE(sym)
	A_BYTECODE(symeval)
	A_BYTECODE(tag)
	A_BYTECODE(type)
	A_BYTECODE(type_local_push)
	A_BYTECODE(type_clos_push)
	A_BYTECODE(variadic)
END_DECLARE_BYTECODES

#ifdef __GNUC__

// use indirect goto when using GCC

typedef void* _bytecode_label;
#define DISPATCH_BYTECODES \
        bytecode_t *pc = static_cast<Closure*>(stack[0])->code(); \
	goto (*(pc->op));
#define NEXT_BYTECODE goto (*((++pc)->op))
#define BYTECODE(x) PASTE_SYMBOLS(label_b_, x)
#define THE_BYTECODE_LABEL(x) &&PASTE_SYMBOLS(label_b_, x)

#else // __GNUC__

// use an enum when using standard C

typedef enum _e_bytecode_label _bytecode_label;
#define DISPATCH_BYTECODES \
	bytecode_t *pc = static_cast<Closure*>(stack[0])->code();\
	switch(pc->op)
#define NEXT_BYTECODE {pc++; continue;}
#define BYTECODE(x) case BYTECODE_ENUM(x)
#define THE_BYTECODE_LABEL(x) BYTECODE_ENUM(x)

#endif // __GNUC__

/*
 * Generic executor
 * An executor represents a built-in function
 */
class Executor {
public:
  virtual ~Executor() {}
  virtual void run(ProcessStack & stack, size_t & reductions) = 0;
};

/*
 * The bytecode read by the reader should be assembled before execution
 * an assembled bytecode is an array of bytecode_t
 * The executor can assume that the bytecodes are correct
 * The assembler must have already catched eventual errors
 */
struct bytecode_t {
  _bytecode_label op; // operation code
  intptr_t val; // simple value argument (may be invalid)
  bytecode_t *seq; // sequence argument (may be invalid)
};

#define INTPARAM(name) intptr_t name = pc->val
#define INTSEQPARAM(name1, name2)\
        intptr_t name1 = pc->val; \
        bytecode_t* name_2 = pc->seq;

// Assemble a sequence of bytecodes
void assemble(BytecodeSeq & seq, bytecode_t* & a_seq);

// Execute a given process
ProcessStatus execute(Process & proc, size_t reductions, bool init = 0);

#endif // EXECUTORS_H
<commit_msg>inc/executors.hpp: corrected name in INTSEQPARAM()<commit_after>#ifndef EXECUTORS_H
#define EXECUTORS_H

#include "processes.hpp"
#include "reader.hpp" // for Bytecode classes

/*
  hl functions are represented by a Closure structure, which has an
  attached bytecode_t array.

  Calling convention:

  proc.stack[0] *must* be a Closure

  proc.stack[0] contains the closure.  If it is a "normal"
  function, proc.stack[1] is the "continuation" function
  and proc.stack[2..n] are the parameters.
  proc.stack.size() is the number of parameters including
  the function itself and the continuation.

  If it is a "continuation" function, proc.stack[1] is always
  the return value. proc.stack.size() will be 2.

  Functions never return.
*/

#define PASTE_SYMBOLS(x,y) x##y

/*
  Not necessary when using GCC.
  NOTE!  We retain this and even add references to
  an _e_bytecode_label type so that modders who
  happen to use *only* GCC will remember to update
  the declarations for the benefit of non-GCC
  users.
*/

#define DECLARE_BYTECODES enum _e_bytecode_label {
#define BYTECODE_ENUM(x) PASTE_SYMBOLS(_bytecode_, x)
#define A_BYTECODE(x) BYTECODE_ENUM(x),
#define END_DECLARE_BYTECODES __null_bytecode };
DECLARE_BYTECODES
	A_BYTECODE(apply)
	A_BYTECODE(apply_invert_k)
	A_BYTECODE(apply_list)
	A_BYTECODE(apply_k_release)
	A_BYTECODE(car)
	A_BYTECODE(car_local_push)
	A_BYTECODE(car_clos_push)
	A_BYTECODE(cdr)
	A_BYTECODE(cdr_local_push)
	A_BYTECODE(cdr_clos_push)
	A_BYTECODE(check_vars)
	A_BYTECODE(closure)
	A_BYTECODE(closure_ref)
	A_BYTECODE(composeo)
	A_BYTECODE(cons)
	A_BYTECODE(b_continue)
	A_BYTECODE(continue_local)
	A_BYTECODE(continue_on_clos)
	A_BYTECODE(global)
	A_BYTECODE(global_set)
	A_BYTECODE(halt)
	A_BYTECODE(halt_local_push)
	A_BYTECODE(halt_clos_push)
	A_BYTECODE(b_if)
	A_BYTECODE(if_local)
	A_BYTECODE(b_int)
	A_BYTECODE(k_closure)
	A_BYTECODE(k_closure_recreate)
	A_BYTECODE(k_closure_reuse)
	A_BYTECODE(lit_nil)
	A_BYTECODE(lit_t)
	A_BYTECODE(local)
	A_BYTECODE(reducto)
	A_BYTECODE(rep)
	A_BYTECODE(rep_local_push)
	A_BYTECODE(rep_clos_push)
	A_BYTECODE(sv)
	A_BYTECODE(sv_local_push)
	A_BYTECODE(sv_clos_push)
	A_BYTECODE(sv_ref)
	A_BYTECODE(sv_ref_local_push)
	A_BYTECODE(sv_ref_clos_push)
	A_BYTECODE(sv_set)
	A_BYTECODE(sym)
	A_BYTECODE(symeval)
	A_BYTECODE(tag)
	A_BYTECODE(type)
	A_BYTECODE(type_local_push)
	A_BYTECODE(type_clos_push)
	A_BYTECODE(variadic)
END_DECLARE_BYTECODES

#ifdef __GNUC__

// use indirect goto when using GCC

typedef void* _bytecode_label;
#define DISPATCH_BYTECODES \
        bytecode_t *pc = static_cast<Closure*>(stack[0])->code(); \
	goto (*(pc->op));
#define NEXT_BYTECODE goto (*((++pc)->op))
#define BYTECODE(x) PASTE_SYMBOLS(label_b_, x)
#define THE_BYTECODE_LABEL(x) &&PASTE_SYMBOLS(label_b_, x)

#else // __GNUC__

// use an enum when using standard C

typedef enum _e_bytecode_label _bytecode_label;
#define DISPATCH_BYTECODES \
	bytecode_t *pc = static_cast<Closure*>(stack[0])->code();\
	switch(pc->op)
#define NEXT_BYTECODE {pc++; continue;}
#define BYTECODE(x) case BYTECODE_ENUM(x)
#define THE_BYTECODE_LABEL(x) BYTECODE_ENUM(x)

#endif // __GNUC__

/*
 * Generic executor
 * An executor represents a built-in function
 */
class Executor {
public:
  virtual ~Executor() {}
  virtual void run(ProcessStack & stack, size_t & reductions) = 0;
};

/*
 * The bytecode read by the reader should be assembled before execution
 * an assembled bytecode is an array of bytecode_t
 * The executor can assume that the bytecodes are correct
 * The assembler must have already catched eventual errors
 */
struct bytecode_t {
  _bytecode_label op; // operation code
  intptr_t val; // simple value argument (may be invalid)
  bytecode_t *seq; // sequence argument (may be invalid)
};

#define INTPARAM(name) intptr_t name = pc->val
#define INTSEQPARAM(name1, name2)\
        intptr_t name1 = pc->val; \
        bytecode_t* name2 = pc->seq;

// Assemble a sequence of bytecodes
void assemble(BytecodeSeq & seq, bytecode_t* & a_seq);

// Execute a given process
ProcessStatus execute(Process & proc, size_t reductions, bool init = 0);

#endif // EXECUTORS_H
<|endoftext|>


<commit_before>#ifndef RIAKPP_CHECK_HPP_
#define RIAKPP_CHECK_HPP_

#include <iostream>
#include <string>
#include <sstream>

#define RIAKPP_INTERNAL_XSTRINGIFY(x) #x
#define RIAKPP_INTERNAL_STRINGIFY(x) RIAKPP_INTERNAL_XSTRINGIFY(x)

#define RIAKPP_INTERNAL_CHECK_ERROR_STREAM(x)                \
  ::riak::internal::check_error_stream {                     \
    __FILE__ ":" RIAKPP_INTERNAL_STRINGIFY(__LINE__) ": ", x \
  }
#define RIAKPP_CHECK(cond)            \
  if (!(cond))                        \
  RIAKPP_INTERNAL_CHECK_ERROR_STREAM( \
      new std::string{"Check '" #cond "' failed"})

#define RIAKPP_INTERNAL_CHECK_OP(id, op, a, b)                            \
  if (::std::string *message =                                            \
          ::riak::internal::Check##id##Impl((a), (b), #a " " #op " " #b)) \
  RIAKPP_INTERNAL_CHECK_ERROR_STREAM(message)

#define RIAKPP_CHECK_EQ(a, b) RIAKPP_INTERNAL_CHECK_OP(Eq, ==, a, b)
#define RIAKPP_CHECK_LE(a, b) RIAKPP_INTERNAL_CHECK_OP(Le, <=, a, b)
#define RIAKPP_CHECK_LT(a, b) RIAKPP_INTERNAL_CHECK_OP(Lt, <, a, b)
#define RIAKPP_CHECK_GE(a, b) RIAKPP_INTERNAL_CHECK_OP(Ge, >=, a, b)
#define RIAKPP_CHECK_GT(a, b) RIAKPP_INTERNAL_CHECK_OP(Gt, >, a, b)

namespace riak {
namespace internal {

#define RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(id, op)                        \
  template <class T, class U>                                               \
  inline std::string *Check##id##Impl(const T &a, const U &b,               \
                                      const char *condition) {              \
    if (a op b) return nullptr;                                             \
    std::stringstream stream{};                                             \
    stream << "Check '" << condition << "' failed ('" << a << "' vs '" << b \
           << "')";                                                         \
    return new std::string{stream.str()};                                   \
  }

RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Eq, == );
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Le, <= );
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Lt, < );
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Ge, >= );
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Gt, > );

#undef RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL

class check_error_stream {
 public:
  check_error_stream(const char *location,
                     std::string *message = nullptr) noexcept;

  template <class T>
  check_error_stream &operator<<(const T& message_piece) {
    if (!additional_message_) {
      additional_message_ = true;
      message_ << ": ";
    }
    message_ << message_piece;
    return *this;
  }

  ~check_error_stream() noexcept;

 private:
  std::stringstream message_;
  bool additional_message_ = false;
};

}  // namespace internal
}  // namespace riak

#endif  // #ifndef RIAKPP_CHECK_HPP_
<commit_msg>added check_ne<commit_after>#ifndef RIAKPP_CHECK_HPP_
#define RIAKPP_CHECK_HPP_

#include <iostream>
#include <string>
#include <sstream>

#define RIAKPP_INTERNAL_XSTRINGIFY(x) #x
#define RIAKPP_INTERNAL_STRINGIFY(x) RIAKPP_INTERNAL_XSTRINGIFY(x)

#define RIAKPP_INTERNAL_CHECK_ERROR_STREAM(x)                \
  ::riak::internal::check_error_stream {                     \
    __FILE__ ":" RIAKPP_INTERNAL_STRINGIFY(__LINE__) ": ", x \
  }
#define RIAKPP_CHECK(cond)            \
  if (!(cond))                        \
  RIAKPP_INTERNAL_CHECK_ERROR_STREAM( \
      new std::string{"Check '" #cond "' failed"})

#define RIAKPP_INTERNAL_CHECK_OP(id, op, a, b)                            \
  if (::std::string *message =                                            \
          ::riak::internal::Check##id##Impl((a), (b), #a " " #op " " #b)) \
  RIAKPP_INTERNAL_CHECK_ERROR_STREAM(message)

#define RIAKPP_CHECK_EQ(a, b) RIAKPP_INTERNAL_CHECK_OP(Eq, ==, a, b)
#define RIAKPP_CHECK_LE(a, b) RIAKPP_INTERNAL_CHECK_OP(Le, <=, a, b)
#define RIAKPP_CHECK_LT(a, b) RIAKPP_INTERNAL_CHECK_OP(Lt, <, a, b)
#define RIAKPP_CHECK_GE(a, b) RIAKPP_INTERNAL_CHECK_OP(Ge, >=, a, b)
#define RIAKPP_CHECK_GT(a, b) RIAKPP_INTERNAL_CHECK_OP(Gt, >, a, b)

namespace riak {
namespace internal {

#define RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(id, op)                        \
  template <class T, class U>                                               \
  inline std::string *Check##id##Impl(const T &a, const U &b,               \
                                      const char *condition) {              \
    if (a op b) return nullptr;                                             \
    std::stringstream stream{};                                             \
    stream << "Check '" << condition << "' failed ('" << a << "' vs '" << b \
           << "')";                                                         \
    return new std::string{stream.str()};                                   \
  }

RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Eq, ==);
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Ne, !=);
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Le, <=);
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Lt, <);
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Ge, >=);
RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL(Gt, >);

#undef RIAKPP_INTERNAL_DEFINE_CHECK_OP_IMPL

class check_error_stream {
 public:
  check_error_stream(const char *location,
                     std::string *message = nullptr) noexcept;

  template <class T>
  check_error_stream &operator<<(const T& message_piece) {
    if (!additional_message_) {
      additional_message_ = true;
      message_ << ": ";
    }
    message_ << message_piece;
    return *this;
  }

  ~check_error_stream() noexcept;

 private:
  std::stringstream message_;
  bool additional_message_ = false;
};

}  // namespace internal
}  // namespace riak

#endif  // #ifndef RIAKPP_CHECK_HPP_
<|endoftext|>


<commit_before>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>
using namespace std;
template<typename T>
auto newcopy(T * item, size_t size, size_t count) -> T*
{
	T * buff = new T[size];
	copy(item, item + count, buff);
	return buff;
}
template <typename T>
class stack
{
public:
	stack();
	stack(stack const &);
	~stack();
	size_t count() const;
	auto push(T const &) -> void;
	T pop();
	auto operator=(stack const & right)->stack &;
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};
template <typename T>
size_t stack<T>::count() const
{
	return count_;
}
template <typename T>
stack<T>::stack():array_size_(0), count_(0), array_(new T[array_size_])
{

}

template<typename T>
stack<T>::stack(stack const & item):array_size_(item.array_size_), count_(item.count_),array_(newcopy(item.array_, item.array_size_,item.count_))
{

}

template <typename T>
stack<T>::~stack()
{
	delete[] array_;
}

template<typename T>
auto stack<T>::push(T const & item) -> void {
	if (count_ == array_size_) {
		size_t size = array_size_ * 2 + (array_size_ == 0) ;
		delete[] array_;
		array_ = newcopy(array_, size, array_size_);
		array_size_ = size;
	}
	++count_;
	array_[count_ - 1] = item;
}

template<typename T>
T stack<T>::pop() {
	if (count_ == 0) {
		throw std::logic_error("Stack is empty!");
	}
	return array_[--count_];
}
template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	delete[] array_;
	count_ = right.count_;
	array_size_ = right.array_size_;
	newcopy(right.array_, array_size_, count_);
	}
	return *this;
}

#endif
<commit_msg>Update stack.cpp<commit_after>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>
using namespace std;
template<typename T>
auto newcopy(T * item, size_t size, size_t count) -> T*
{
	T * buff = new T[size];
	copy(item, item + count, buff);
	return buff;
}
template <typename T>
class stack
{
public:
	stack();
	stack(stack const &);
	~stack();
	size_t count() const;
	auto push(T const &) -> void;
	T pop();
	auto operator=(stack const & right)->stack &;
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};
template <typename T>
size_t stack<T>::count() const
{
	return count_;
}
template <typename T>
stack<T>::stack():array_size_(0), count_(0), array_(new T[array_size_])
{

}

template<typename T>
stack<T>::stack(stack const & item):array_size_(item.array_size_), count_(item.count_),array_(newcopy(item.array_, item.array_size_,item.count_))
{

}

template <typename T>
stack<T>::~stack()
{
	delete[] array_;
}

template<typename T>
auto stack<T>::push(T const & item) -> void {
	if (count_ == array_size_) {
		size_t size = array_size_ * 2 + (array_size_ == 0) ;
		array_ = newcopy(array_, size, array_size_);
		delete[] array_;
		array_size_ = size;
	}
	array_[count_] = item;
	++count_;
}

template<typename T>
T stack<T>::pop() {
	if (count_ == 0) {
		throw std::logic_error("Stack is empty!");
	}
	return array_[--count_];
}
template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	delete[] array_;
	count_ = right.count_;
	array_size_ = right.array_size_;
	newcopy(right.array_, array_size_, count_);
	}
	return *this;
}

#endif
<|endoftext|>


<commit_before>#include "stack.hpp"
#include <stdexcept>
#ifndef STACK_CPP
#define STACK_CPP

bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения тдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(prt_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_());
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
stack<T>::stack(size_t size) : allocator_(size)
{}

template<typename T>
auto stack<T>::operator =(stack const & other)-> stack &
{
	if (this != &other)
	{
		(allocator<T>(other.allocator_)).swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const ->bool
{
return allocator_.empty();
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template<typename T>
auto stack<T>::pop()->void
{
	if (allocator_.count() == 0) throw std::logic_error("Empty");
	allocator_.destroy(allocator_.get() + (this->count() - 1));
}

template<typename T>
auto stack<T>::top()->T&
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::top()const->T const &
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::throw_is_empty()const->void
{
throw("Stack is empty");
}

#endif
<commit_msg>Update stack.cpp<commit_after>#include "stack.hpp"
#include <stdexcept>
#ifndef STACK_CPP
#define STACK_CPP

bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения тдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr, prt_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_());
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
stack<T>::stack(size_t size) : allocator_(size)
{}

template<typename T>
auto stack<T>::operator =(stack const & other)-> stack &
{
	if (this != &other)
	{
		(allocator<T>(other.allocator_)).swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const ->bool
{
return allocator_.empty();
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template<typename T>
auto stack<T>::pop()->void
{
	if (allocator_.count() == 0) throw std::logic_error("Empty");
	allocator_.destroy(allocator_.get() + (this->count() - 1));
}

template<typename T>
auto stack<T>::top()->T&
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::top()const->T const &
{
	if (this->count() > 0) return(*(allocator_.get() + this->count() - 1));
	else this->throw_is_empty();
}

template<typename T>
auto stack<T>::throw_is_empty()const->void
{
throw("Stack is empty");
}

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <new>
#include <thread>
#include <mutex>
#include <memory>

template <typename T>
class stack
{
public:
	stack() noexcept;
	~stack() noexcept;
	stack(stack<T> const&)/*strong*/;
	stack& operator=(stack<T> const&)/*strong*/;
	size_t count()const noexcept;
	void push(T const&)/*strong*/;
	auto pop() -> std::shared_ptr<T>/*strong*/;
	void print(std::ostream&stream)const /*strong*/;
	bool empty()const noexcept;
private:
	void swap(stack<T>&)noexcept;
	mutable std::mutex mutex_;
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() noexcept : array_{ nullptr }, array_size_{ 0 }, count_{ 0 } {}
template <typename T>
stack<T>::~stack()noexcept
{
	delete[] array_;
}
template <typename T>
stack<T>::stack(stack<T> const& other)
{
	std::lock_guard<std::mutex> lock(other.mutex_);
	T new_array = new T [other.array_size_];
	array_size_ = other.array_size_;
	count_ = other.count_;
	array_ = new_array;
	try
	{
		std::copy(other.array_, other.array_ + count_, array_);
	}
	catch( ... )
	{
		std::cerr << "ERROR" << std::endl;
		delete[] array_;
	}
}
template <typename T>
stack<T>& stack<T>::operator=(stack<T> const & other)
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (&other != this)
		stack(other).swap(*this);
	return *this;
}
template <typename T>
size_t stack<T>::count()const noexcept
{
	std::lock_guard<std::mutex> lock(mutex_);
	return count_;
}
template <typename T>
void stack<T>::push(T const & value)
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (empty())
	{
		array_size_ = 1;
		array_ = new T[array_size_]();
	}
	else if (array_size_ == count_)
	{
		try
		{
		        array_size_ *= 2;
		        T * new_array = new T[array_size_]();
		        std::copy(array_, array_ + count_, new_array);
		        delete[] array_;
		        array_ = new_array;
		}
		catch(std::bad_alloc)
	        {
		        std::cerr << "bad_alloc caught" << std::endl;
	        }
	}
	array_[count_] = value;
	count_++;
}
template <typename T>
auto stack<T>::pop() -> std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
	auto top = std::make_shared<T>(array_[count_ - 1]);
	if (empty())
		throw std::logic_error("Stack is empty");
	--count_;
	return top;
}
template <typename T>
void stack<T>::print(std::ostream&stream)const
{
	mutex_.lock();
	if(!empty())
	{
	        for (unsigned int i = 0; i < count_; ++i)
		        stream << array_[i] << " ";
	        stream << std::endl;
	}
	mutex_.unlock();
}
template <typename T>
void stack<T>::swap(stack<T>& other)noexcept
{
	std::lock(mutex_, other.mutex_);
	std::swap(array_, other.array_);
	std::swap(array_size_, other.array_size_);
	std::swap(count_, other.count_);
	mutex_.unlock();
	other.mutex_.unlock();
}
template <typename T>
bool stack<T>::empty()const noexcept
{
	std::lock_guard<std::mutex> lock(mutex_);
	return (count_ == 0);
}
<commit_msg>Update stack.hpp<commit_after>#include <iostream>
#include <algorithm>
#include <new>
#include <thread>
#include <mutex>
#include <memory>

template <typename T>
class stack
{
public:
	stack() noexcept;
	~stack() noexcept;
	stack(stack<T> const&)/*strong*/;
	stack& operator=(stack<T> const&)/*strong*/;
	size_t count()const noexcept;
	void push(T const&)/*strong*/;
	auto pop() -> std::shared_ptr<T>/*strong*/;
	bool empty()const noexcept;
private:
	void swap(stack<T>&)noexcept;
	mutable std::mutex mutex_;
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() noexcept : array_{ nullptr }, array_size_{ 0 }, count_{ 0 } {}
template <typename T>
stack<T>::~stack()noexcept
{
	delete[] array_;
}
template <typename T>
stack<T>::stack(stack<T> const& other)
{
	std::lock_guard<std::mutex> lock(other.mutex_);
	T new_array = new T [other.array_size_];
	array_size_ = other.array_size_;
	count_ = other.count_;
	array_ = new_array;
	try
	{
		std::copy(other.array_, other.array_ + count_, array_);
	}
	catch( ... )
	{
		std::cerr << "ERROR" << std::endl;
		delete[] array_;
	}
}
template <typename T>
stack<T>& stack<T>::operator=(stack<T> const & other)
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (&other != this)
		stack(other).swap(*this);
	return *this;
}
template <typename T>
size_t stack<T>::count()const noexcept
{
	std::lock_guard<std::mutex> lock(mutex_);
	return count_;
}
template <typename T>
void stack<T>::push(T const & value)
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (empty())
	{
		array_size_ = 1;
		array_ = new T[array_size_]();
	}
	else if (array_size_ == count_)
	{
		try
		{
		        array_size_ *= 2;
		        T * new_array = new T[array_size_]();
		        std::copy(array_, array_ + count_, new_array);
		        delete[] array_;
		        array_ = new_array;
		}
		catch(std::bad_alloc)
	        {
		        std::cerr << "bad_alloc caught" << std::endl;
	        }
	}
	array_[count_] = value;
	count_++;
}
template <typename T>
auto stack<T>::pop() -> std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
	auto top = std::make_shared<T>(array_[count_ - 1]);
	if (empty())
		throw std::logic_error("Stack is empty");
	--count_;
	return top;
}
template <typename T>
void stack<T>::swap(stack<T>& other)noexcept
{
	std::lock(mutex_, other.mutex_);
	std::swap(array_, other.array_);
	std::swap(array_size_, other.array_size_);
	std::swap(count_, other.count_);
	mutex_.unlock();
	other.mutex_.unlock();
}
template <typename T>
bool stack<T>::empty()const noexcept
{
	std::lock_guard<std::mutex> lock(mutex_);
	return (count_ == 0);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <new>
#include <stdexcept>
#include <vector>
#include <memory>
#include <mutex>
#include <thread>

class bitset
{
public:
explicit
bitset( size_t size ) /*strong*/;

bitset( bitset const & other ) = delete;
auto operator =( bitset const & other ) -> bitset & = delete;

bitset( bitset && other ) = delete;
auto operator =( bitset && other ) -> bitset & = delete;

auto set( size_t index ) /*strong*/ -> void;
auto reset( size_t index ) throw(std::out_of_range)/*strong*/ -> void;
auto test( size_t index ) const throw(std::out_of_range)/*strong*/ -> bool;

auto size() const /*noexcept*/ -> size_t;
auto counter() const /*noexcept*/ -> size_t;

private:
std::unique_ptr<bool[]> ptr_;
size_t size_;
size_t counter_;
};
bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения отдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}

template <typename T>
class allocator
{
public:
explicit
allocator( std::size_t size = 0 ) /*strong*/;
allocator( allocator const & other ) /*strong*/;
auto operator =( allocator const & other ) -> allocator & = delete;
~allocator();

auto resize() /*strong*/ -> void;

auto construct(T * ptr, T const & value ) /*strong*/ -> void;
auto destroy( T * ptr ) /*noexcept*/ -> void;

auto get() /*noexcept*/ -> T *;
auto get() const /*noexcept*/ -> T const *;

auto count() const /*noexcept*/ -> size_t;
auto full() const /*noexcept*/ -> bool;
auto empty() const /*noexcept*/ -> bool;
private:
auto destroy( T * first, T * last ) /*noexcept*/ -> void;
auto swap( allocator & other ) /*noexcept*/ -> void;

private:

T * ptr_;
size_t size_;
std::unique_ptr<bitset> map_;
};
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr_, ptr_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_);
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
}

template <typename T>
class stack
{
public:
explicit
stack( size_t size = 0 );
stack (stack const & other);
auto operator =( stack const & other ) /*strong*/ -> stack &;

auto empty() const /*noexcept*/ -> bool;
auto count() const /*noexcept*/ -> size_t;

auto push( T const & value ) /*strong*/ -> shared_ptr<T>;
auto pop() /*strong*/ -> void;
auto top() /*strong*/ -> T &;
auto top() const /*strong*/ -> T const &;

private:
allocator<T> allocator_;
mutable std::mutex mutex_;

auto throw_is_empty() const -> void;
};

template<typename T>
stack<T>::stack(size_t size) : allocator_(size),mutex_() {};

template <typename T>
 stack<T>::stack(stack const & other) : allocator_(0), mutex_()
 {
 	std::lock_guard<std::mutex> lock(other.mutex_);
 	allocator<T>(other.allocator_).swap(allocator_);
}

template <typename T>
auto stack<T>::operator=(const stack &other)->stack&
{
	if (this != &other)
	{
		std::lock(mutex_, other.mutex_);
 		std::lock_guard<std::mutex> lock_a(mutex_, std::adopt_lock);
 		std::lock_guard<std::mutex> lock_b(other.mutex_, std::adopt_lock);
		stack(other).allocator_.swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const->bool
{
	std::lock_guard<std::mutex> lock(mutex_);
	return (allocator_.count() == 0);
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template <typename T>
auto stack<T>::pop()->std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
			if(allocator_.empty()) throw std::logic_error("Empty!");
				std::shared_ptr<T> const result(std::make_shared<T>(std::move(allocator_.get()[allocator_.count()-1])));
			allocator_.destroy(allocator_.get() + allocator_.count() - 1);
			return result;
}

<commit_msg>Update stack.hpp<commit_after>#include <iostream>
#include <new>
#include <stdexcept>
#include <vector>
#include <memory>
#include <mutex>
#include <thread>

class bitset
{
public:
explicit
bitset( size_t size ) /*strong*/;

bitset( bitset const & other ) = delete;
auto operator =( bitset const & other ) -> bitset & = delete;

bitset( bitset && other ) = delete;
auto operator =( bitset && other ) -> bitset & = delete;

auto set( size_t index ) /*strong*/ -> void;
auto reset( size_t index ) throw(std::out_of_range)/*strong*/ -> void;
auto test( size_t index ) const throw(std::out_of_range)/*strong*/ -> bool;

auto size() const /*noexcept*/ -> size_t;
auto counter() const /*noexcept*/ -> size_t;

private:
std::unique_ptr<bool[]> ptr_;
size_t size_;
size_t counter_;
};
bitset::bitset(size_t size) : ptr_(std::make_unique<bool[]>(size)),size_(size),counter_(0)
{}

auto bitset::set(size_t index)->void //инициализация всех битов единицами или изменение значения отдельного бита
{
	if (index >= 0 && index < size_)
	{
		ptr_[index] = true; ++counter_;
	}
	else throw("problem with index");
}

auto bitset::reset(size_t index) throw(std::out_of_range) -> void //обнуление указанных битов
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	ptr_[index] = false;
	--counter_;
}

auto bitset::test(size_t index) const throw(std::out_of_range) -> bool //возвращает значение указанного бита
{
	if (index >= size_)
	{
		throw (std::out_of_range("problem with index"));
	}
	return ptr_[index];
}

auto bitset::size() const -> size_t
{
	return size_;
}
auto bitset::counter() const -> size_t
{
	return counter_;
}

template <typename T>
class allocator
{
public:
explicit
allocator( std::size_t size = 0 ) /*strong*/;
allocator( allocator const & other ) /*strong*/;
auto operator =( allocator const & other ) -> allocator & = delete;
~allocator();

auto resize() /*strong*/ -> void;

auto construct(T * ptr, T const & value ) /*strong*/ -> void;
auto destroy( T * ptr ) /*noexcept*/ -> void;

auto get() /*noexcept*/ -> T *;
auto get() const /*noexcept*/ -> T const *;

auto count() const /*noexcept*/ -> size_t;
auto full() const /*noexcept*/ -> bool;
auto empty() const /*noexcept*/ -> bool;
private:
auto destroy( T * first, T * last ) /*noexcept*/ -> void;
auto swap( allocator & other ) /*noexcept*/ -> void;

private:

T * ptr_;
size_t size_;
std::unique_ptr<bitset> map_;
};
template<typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)operator new(size*sizeof(T))), size_(size), map_(std::make_unique<bitset>(size))//конструктор с параметром
{}

template<typename T>
allocator<T>::allocator(allocator const& other) : allocator<T>(other.size_) //конструктор копирования
{
	for (size_t i=0; i < size_; i++)
	{
		if (map_->test(i))
		{
			destroy(ptr_, ptr_ +i);
		}
	construct(ptr_ + i, other.ptr_[i]);
}}

template<typename T>
allocator<T>::~allocator()
{
	if (this->count() > 0)
	{
		destroy(ptr_, ptr_ + size_);
	}
	operator delete(ptr_);
}

template<typename T> //увеличение памяти
auto allocator<T>::resize()->void
{
	allocator<T> alloc(size_ * 2 + (size_ == 0));
	for (size_t i = 0; i < size_; ++i) if(map_->test(i)) alloc.construct(alloc.get() + i, ptr_[i]);
	this->swap(alloc);
}

template<typename T>
auto allocator<T>::construct(T * ptr, T const & value)->void
{
	if (ptr >= ptr_&&ptr < ptr_ + size_)
	{
		new(ptr)T(value);
		map_->set(ptr - ptr_);
	}
	else { throw("error"); }
}
template <typename T>
auto allocator<T>::destroy(T * ptr)->void
{
if (ptr < ptr_ || ptr >= ptr_ + size_ || map_->test(ptr-ptr_) == false)
{
		throw std::out_of_range("Error");
}
	ptr->~T();
	map_->reset(ptr - ptr_);

}

template<typename T> //получаем ptr_
auto allocator<T>::get()-> T* { return ptr_; }

template<typename T>
auto allocator<T>::get() const -> T const * { return ptr_; }

template<typename T>
auto allocator<T>::count() const -> size_t{ return map_->counter(); }

template<typename T> //заполненность
auto allocator<T>::full() const -> bool { return (map_->counter() == size_); }

template<typename T>
auto allocator<T>::empty() const -> bool { return (map_->counter() == 0); }

template<typename T>
auto allocator<T>::destroy(T * first, T * last)->void
{
	if(first>=ptr_&&last<=ptr_+this->count())
		for (; first != last; ++first)
		{
			destroy(&*first);
		}
}

template<typename T>
auto allocator<T>::swap(allocator & other)->void{
	std::swap(ptr_, other.ptr_);
	std::swap(size_, other.size_);
	std::swap(map_, other.map_);
}

template <typename T>
class stack
{
public:
explicit
stack( size_t size = 0 );
stack (stack const & other);
auto operator =( stack const & other ) /*strong*/ -> stack &;

auto empty() const /*noexcept*/ -> bool;
auto count() const /*noexcept*/ -> size_t;

auto push( T const & value ) /*strong*/ -> void;
auto pop() /*strong*/ -> shared_ptr<T>;

private:
allocator<T> allocator_;
mutable std::mutex mutex_;

auto throw_is_empty() const -> void;
};

template<typename T>
stack<T>::stack(size_t size) : allocator_(size),mutex_() {};

template <typename T>
 stack<T>::stack(stack const & other) : allocator_(0), mutex_()
 {
 	std::lock_guard<std::mutex> lock(other.mutex_);
 	allocator<T>(other.allocator_).swap(allocator_);
}

template <typename T>
auto stack<T>::operator=(const stack &other)->stack&
{
	if (this != &other)
	{
		std::lock(mutex_, other.mutex_);
 		std::lock_guard<std::mutex> lock_a(mutex_, std::adopt_lock);
 		std::lock_guard<std::mutex> lock_b(other.mutex_, std::adopt_lock);
		stack(other).allocator_.swap(allocator_);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const->bool
{
	std::lock_guard<std::mutex> lock(mutex_);
	return (allocator_.count() == 0);
}

template<typename T>
auto stack<T>::count()const->size_t
{
return allocator_.count();
}

template<typename T>
auto stack<T>::push(T const & value)->void
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (allocator_.full()) allocator_.resize();
	allocator_.construct(allocator_.get() + this->count(), value);
}

template <typename T>
auto stack<T>::pop()->std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
			if(allocator_.empty()) throw std::logic_error("Empty!");
				std::shared_ptr<T> const result(std::make_shared<T>(std::move(allocator_.get()[allocator_.count()-1])));
			allocator_.destroy(allocator_.get() + allocator_.count() - 1);
			return result;
}

<|endoftext|>


<commit_before>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>

template <typename T1, typename T2>
void construct(T1 * ptr, T2 const & value) {
    new(ptr) T1 (value);
}

template <typename T>
void destroy(T * ptr) noexcept
{
    ptr->~T();
}

template <typename FwdIter>
void destroy(FwdIter first, FwdIter last) noexcept
{
    for (; first != last; ++first) {
        destroy(&*first);
    }
}

template <typename T>
class allocator
{
protected:
    allocator(size_t size = 0);
    ~allocator();
    auto swap(allocator & other) -> void;

    allocator(allocator const &) = delete;
    auto operator =(allocator const &) -> allocator & = delete;

    T * ptr_;
    size_t size_;
    size_t count_;
};

template<typename T>
allocator<T>::allocator(size_t size) :
	ptr_(static_cast<T *>(size == 0 ? nullptr : operator new(size * sizeof(T)))),
	size_(0),
	count_(size) {
}

template<typename T>
allocator<T>::~allocator() {
	delete ptr_;
}

template<typename T>
auto allocator<T>::swap(allocator & other) -> void {
	std::swap(ptr_, other.ptr_);
	std::swap(count_, other.count_);
	std::swap(size_, other.size_);
}

template <typename T>
class stack : private allocator<T>
{
public:
	stack(size_t size = 0 ); //noexcept
	stack(stack const &);  //strong
	~stack(); //noexcept
	size_t count() const;  //noexcept
	auto push(T const &) -> void; //strong
	void pop(); //strong
	const T& top(); //strong
	auto operator=(stack const & right)->stack &; //strong
	auto empty() const -> bool; //noexcept

};
template <typename T>
size_t stack<T>::count() const
{
	return allocator<T>::count_;
}
template <typename T>
stack<T>::stack(size_t size):allocator<T>(size){}

template <typename T>
stack<T>::stack(const stack& item) : allocator<T>(item.size_){
	for (size_t i = 0; i < item.count_; i++) construct(allocator<T>::ptr_ + i, item.ptr_[i]);
	allocator<T>::count_ = item.count_;
};

template <typename T>
stack<T>::~stack()
{
}

template <typename T>
void stack<T>::push(T const &item){
	if (allocator<T>::count_ == allocator<T>::size_) {
		size_t array_size = allocator<T>::size_ * 2 + (allocator<T>::size_ == 0);
		stack<T> temp(array_size);
		while (temp.count() < allocator<T>::count_) temp.push(allocator<T>::ptr_[temp.count()]);
		this->swap(temp);
	}
	construct(allocator<T>::ptr_ + allocator<T>::count_, item);
	++allocator<T>::count_;
}

template<typename T>
void stack<T>::pop() {
	if (allocator<T>::count_ == 0) {
		throw std::logic_error("Stack is empty!");
	} else {
		allocator<T>::count_--;
	}
}

template<typename T>
const T& stack<T>::top()
{
	if (allocator<T>::count_ == 0) {
		throw ("Stack is empty!");
	}
	return allocator<T>::ptr_[allocator<T>::count_ - 1];
}

template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	stack<T> temp (right.size_);
	while (temp.count_ < right.count_){
		construct(temp.ptr_ + temp.count_, right.ptr_[temp.count_]);
		++temp.count_;
	}
	this -> swap(temp);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const -> bool{
	if (allocator<T>::count_ == 0){
		return true;
	} else{
		return false;
	}
}

#endif
<commit_msg>Update stack.hpp<commit_after>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>

template <typename T1, typename T2>
void construct(T1 * ptr, T2 const & value) {
    new(ptr) T1 (value);
}

template <typename T>
void destroy(T * ptr) noexcept
{
    ptr->~T();
}

template <typename FwdIter>
void destroy(FwdIter first, FwdIter last) noexcept
{
    for (; first != last; ++first) {
        destroy(&*first);
    }
}

template <typename T>
class allocator
{
protected:
    allocator(size_t size = 0);
    ~allocator();
    auto swap(allocator & other) -> void;

    allocator(allocator const &) = delete;
    auto operator =(allocator const &) -> allocator & = delete;

    T * ptr_;
    size_t size_;
    size_t count_;
};

template <typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)(operator new(size*sizeof(T)))), size_(size), count_(0){};

template<typename T>
allocator<T>::~allocator(){ operator delete(ptr_); }

template<typename T>
auto allocator<T>::swap(allocator & other) -> void {
	std::swap(ptr_, other.ptr_);
	std::swap(count_, other.count_);
	std::swap(size_, other.size_);
}

template <typename T>
class stack : private allocator<T>
{
public:
	stack(size_t size = 0 ); //noexcept
	stack(stack const &);  //strong
	~stack(); //noexcept
	size_t count() const;  //noexcept
	auto push(T const &) -> void; //strong
	void pop(); //strong
	const T& top(); //strong
	auto operator=(stack const & right)->stack &; //strong
	auto empty() const -> bool; //noexcept

};
template <typename T>
size_t stack<T>::count() const
{
	return allocator<T>::count_;
}
template <typename T>
stack<T>::stack(size_t size):allocator<T>(size){}

template <typename T>
stack<T>::stack(const stack& item) : allocator<T>(item.size_){
	for (size_t i = 0; i < item.count_; i++) construct(allocator<T>::ptr_ + i, item.ptr_[i]);
	allocator<T>::count_ = item.count_;
};

template <typename T>
stack<T>::~stack()
{
}

template <typename T>
void stack<T>::push(T const &item){
	if (allocator<T>::count_ == allocator<T>::size_) {
		size_t array_size = allocator<T>::size_ * 2 + (allocator<T>::size_ == 0);
		stack<T> temp(array_size);
		while (temp.count() < allocator<T>::count_) temp.push(allocator<T>::ptr_[temp.count()]);
		this->swap(temp);
	}
	construct(allocator<T>::ptr_ + allocator<T>::count_, item);
	++allocator<T>::count_;
}

template<typename T>
void stack<T>::pop() {
	if (allocator<T>::count_ == 0) {
		throw std::logic_error("Stack is empty!");
	} else {
		allocator<T>::count_--;
	}
}

template<typename T>
const T& stack<T>::top()
{
	if (allocator<T>::count_ == 0) {
		throw ("Stack is empty!");
	}
	return allocator<T>::ptr_[allocator<T>::count_ - 1];
}

template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	stack<T> temp (right.size_);
	while (temp.count_ < right.count_){
		construct(temp.ptr_ + temp.count_, right.ptr_[temp.count_]);
		++temp.count_;
	}
	this -> swap(temp);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const -> bool{
	if (allocator<T>::count_ == 0){
		return true;
	} else{
		return false;
	}
}

#endif
<|endoftext|>


<commit_before>#pragma once

#include <UtH/UtHEngine.hpp>
class TitleScene : public uth::Scene
{

	enum class LayerId : char
	{
		TittleBackground,
		Buttons
	};

	std::map<const LayerId, uth::Layer*> m_layers;

	uth::Layer& getLayer(LayerId id);

public: // Every one of these public functions are required.
	TitleScene();
	~TitleScene();

	virtual bool Init();
	virtual bool DeInit();

	virtual void Update(float dt) override;

};<commit_msg>started to do menus/buttons<commit_after>#pragma once

#include <UtH/UtHEngine.hpp>

class Button : public uth::GameObject
{

	bool m_isPressed();

public:

	Button(uth::Texture,uth::AnimatedSprite);
	~Button();

	bool IsPressed();

};

class TitleScene : public uth::Scene
{

	enum class LayerId : char
	{
		TittleBackground,
		Buttons
	};

	std::map<const LayerId, uth::Layer*> m_layers;

	uth::Layer& getLayer(LayerId id);

public: // Every one of these public functions are required.
	TitleScene();
	~TitleScene();

	virtual bool Init();
	virtual bool DeInit();

	virtual void Update(float dt) override;

};<|endoftext|>


<commit_before>//
//  ArgumentException.hpp
//  integral
//
//  Copyright (C) 2013, 2014, 2016  André Pereira Henriques
//  aphenriques (at) outlook (dot) com
//
//  This file is part of integral.
//
//  integral is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  integral 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 integral.  If not, see <http://www.gnu.org/licenses/>.
//

#ifndef integral_ArgumentException_hpp
#define integral_ArgumentException_hpp

#include <cstddef>
#include <stdexcept>
#include <exception>
#include <string>
#include <lua.hpp>

namespace integral {
    class ArgumentException : public std::invalid_argument {
    public:
        // necessary because of the user-defined destructor
        ArgumentException(const ArgumentException &) = default;
        ArgumentException(ArgumentException &) = default;
        ArgumentException(ArgumentException &&) = default;

        // this is necessary (see definition)
        ~ArgumentException() override;

        static ArgumentException createTypeErrorException(lua_State *luaState, int index, const std::string &userDataName);

        inline ArgumentException(lua_State *luaState, int index, const std::string &extraMessage);
        inline ArgumentException(lua_State *luaState, std::size_t maximumNumberOfArguments, std::size_t actualNumberOfArguments);

    private:
        static bool findField (lua_State *luaState, int index, int level);
        static bool pushGlobalFunctionName (lua_State *L, lua_Debug *debugInfo);
        static std::string getExceptionMessage(lua_State *luaState, int index, const std::string &extraMessage);
        static std::string getExceptionMessage(lua_State *luaState, std::size_t maximumNumberOfArguments, std::size_t actualNumberOfArguments);
    };

    //--

    inline ArgumentException::ArgumentException(lua_State *luaState, int index, const std::string &extraMessage) : std::invalid_argument(getExceptionMessage(luaState, index, extraMessage)) {}

    inline ArgumentException::ArgumentException(lua_State *luaState, std::size_t maximumNumberOfArguments, std::size_t actualNumberOfArguments) : std::invalid_argument(getExceptionMessage(luaState, maximumNumberOfArguments, actualNumberOfArguments)) {}
}

#endif
<commit_msg>code formatting<commit_after>//
//  ArgumentException.hpp
//  integral
//
//  Copyright (C) 2013, 2014, 2016  André Pereira Henriques
//  aphenriques (at) outlook (dot) com
//
//  This file is part of integral.
//
//  integral is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  integral 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 integral.  If not, see <http://www.gnu.org/licenses/>.
//

#ifndef integral_ArgumentException_hpp
#define integral_ArgumentException_hpp

#include <cstddef>
#include <stdexcept>
#include <exception>
#include <string>
#include <lua.hpp>

namespace integral {
    class ArgumentException : public std::invalid_argument {
    public:
        // necessary because of the user-defined destructor
        ArgumentException(const ArgumentException &) = default;
        ArgumentException(ArgumentException &) = default;
        ArgumentException(ArgumentException &&) = default;

        // this is necessary (see definition)
        ~ArgumentException() override;

        static ArgumentException createTypeErrorException(lua_State *luaState, int index, const std::string &userDataName);

        inline ArgumentException(lua_State *luaState, int index, const std::string &extraMessage);
        inline ArgumentException(lua_State *luaState, std::size_t maximumNumberOfArguments, std::size_t actualNumberOfArguments);

    private:
        static bool findField(lua_State *luaState, int index, int level);
        static bool pushGlobalFunctionName(lua_State *L, lua_Debug *debugInfo);
        static std::string getExceptionMessage(lua_State *luaState, int index, const std::string &extraMessage);
        static std::string getExceptionMessage(lua_State *luaState, std::size_t maximumNumberOfArguments, std::size_t actualNumberOfArguments);
    };

    //--

    inline ArgumentException::ArgumentException(lua_State *luaState, int index, const std::string &extraMessage) : std::invalid_argument(getExceptionMessage(luaState, index, extraMessage)) {}

    inline ArgumentException::ArgumentException(lua_State *luaState, std::size_t maximumNumberOfArguments, std::size_t actualNumberOfArguments) : std::invalid_argument(getExceptionMessage(luaState, maximumNumberOfArguments, actualNumberOfArguments)) {}
}

#endif
<|endoftext|>


<commit_before><commit_msg>Revert 127030 - chromeos: Do not peek at /home/chronos/user/Downloads<commit_after><|endoftext|>


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

#include "webkit/chromeos/fileapi/cros_mount_point_provider.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/utf_string_conversions.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFileSystem.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "webkit/chromeos/fileapi/file_access_permissions.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
#include "webkit/fileapi/file_system_operation.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/native_file_util.h"
#include "webkit/glue/webkit_glue.h"

namespace chromeos {

typedef struct {
  const char* local_root_path;
  const char* web_root_path;
} FixedExposedPaths;

const char kChromeUIScheme[] = "chrome";

// Top level file system elements exposed in FileAPI in ChromeOS:
FixedExposedPaths fixed_exposed_paths[] = {
    {"/home/chronos/user/", "Downloads"},
    {"/media",              "archive"},
    {"/media",              "removable"},
};

CrosMountPointProvider::CrosMountPointProvider(
    scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy)
    : special_storage_policy_(special_storage_policy),
      file_access_permissions_(new FileAccessPermissions()),
      local_file_util_(
          new fileapi::LocalFileUtil(new fileapi::NativeFileUtil())) {
  for (size_t i = 0; i < arraysize(fixed_exposed_paths); i++) {
    mount_point_map_.insert(std::pair<std::string, FilePath>(
        std::string(fixed_exposed_paths[i].web_root_path),
        FilePath(std::string(fixed_exposed_paths[i].local_root_path))));
  }
}

CrosMountPointProvider::~CrosMountPointProvider() {
}

// TODO(zelidrag) share with SandboxMountPointProvider impl.
std::string GetOriginIdentifierFromURL(
    const GURL& url) {
  WebKit::WebSecurityOrigin web_security_origin =
      WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
  return web_security_origin.databaseIdentifier().utf8();
}

bool CrosMountPointProvider::GetRootForVirtualPath(
    const FilePath& virtual_path, FilePath* root_path) {
  std::vector<FilePath::StringType> components;
  virtual_path.GetComponents(&components);
  if (components.size() < 1) {
    return false;
  }

  base::AutoLock locker(lock_);
  // Check if this root mount point is exposed by this provider.
  MountPointMap::iterator iter = mount_point_map_.find(components[0]);
  if (iter == mount_point_map_.end()) {
    return false;
  }
  *root_path = iter->second;
  return true;
}

void CrosMountPointProvider::ValidateFileSystemRoot(
    const GURL& origin_url,
    fileapi::FileSystemType type,
    bool create,
    const ValidateFileSystemCallback& callback) {
  // Nothing to validate for external filesystem.
  DCHECK(type == fileapi::kFileSystemTypeExternal);
  callback.Run(base::PLATFORM_FILE_OK);
}

FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread(
    const GURL& origin_url,
    fileapi::FileSystemType type,
    const FilePath& virtual_path,
    bool create) {
  DCHECK(type == fileapi::kFileSystemTypeExternal);
  FilePath root_path;
  if (!GetRootForVirtualPath(virtual_path, &root_path))
    return FilePath();

  return root_path;
}

bool CrosMountPointProvider::IsAccessAllowed(const GURL& origin_url,
                                             fileapi::FileSystemType type,
                                             const FilePath& virtual_path) {
  if (type != fileapi::kFileSystemTypeExternal)
    return false;

  // Permit access to mount points from internal WebUI.
  if (origin_url.SchemeIs(kChromeUIScheme))
    return true;

  std::string extension_id = origin_url.host();
  // Check first to make sure this extension has fileBrowserHander permissions.
  if (!special_storage_policy_->IsFileHandler(extension_id))
    return false;

  return file_access_permissions_->HasAccessPermission(extension_id,
                                                       virtual_path);
}

// TODO(zelidrag): Share this code with SandboxMountPointProvider impl.
bool CrosMountPointProvider::IsRestrictedFileName(const FilePath& path) const {
  return false;
}

void CrosMountPointProvider::AddMountPoint(FilePath mount_point) {
  base::AutoLock locker(lock_);
  mount_point_map_.erase(mount_point.BaseName().value());
  mount_point_map_.insert(std::pair<std::string, FilePath>(
      mount_point.BaseName().value(), mount_point.DirName()));
}

void CrosMountPointProvider::RemoveMountPoint(FilePath mount_point) {
  base::AutoLock locker(lock_);
  mount_point_map_.erase(mount_point.BaseName().value());
}

void CrosMountPointProvider::GrantFullAccessToExtension(
    const std::string& extension_id) {
  DCHECK(special_storage_policy_->IsFileHandler(extension_id));
  if (!special_storage_policy_->IsFileHandler(extension_id))
    return;
  for (MountPointMap::const_iterator iter = mount_point_map_.begin();
       iter != mount_point_map_.end();
       ++iter) {
    GrantFileAccessToExtension(extension_id, FilePath(iter->first));
  }
}

void CrosMountPointProvider::GrantFileAccessToExtension(
    const std::string& extension_id, const FilePath& virtual_path) {
  // All we care about here is access from extensions for now.
  DCHECK(special_storage_policy_->IsFileHandler(extension_id));
  if (!special_storage_policy_->IsFileHandler(extension_id))
    return;
  file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
}

void CrosMountPointProvider::RevokeAccessForExtension(
      const std::string& extension_id) {
  file_access_permissions_->RevokePermissions(extension_id);
}

std::vector<FilePath> CrosMountPointProvider::GetRootDirectories() const {
  std::vector<FilePath> root_dirs;
  for (MountPointMap::const_iterator iter = mount_point_map_.begin();
       iter != mount_point_map_.end();
       ++iter) {
    root_dirs.push_back(iter->second.Append(iter->first));
  }
  return root_dirs;
}

fileapi::FileSystemFileUtil* CrosMountPointProvider::GetFileUtil() {
  return local_file_util_.get();
}

fileapi::FileSystemOperationInterface*
CrosMountPointProvider::CreateFileSystemOperation(
    const GURL& origin_url,
    fileapi::FileSystemType file_system_type,
    const FilePath& virtual_path,
    scoped_ptr<fileapi::FileSystemCallbackDispatcher> dispatcher,
    base::MessageLoopProxy* file_proxy,
    fileapi::FileSystemContext* context) const {
  // TODO(satorux,zel): instantiate appropriate FileSystemOperation that
  // implements async/remote operations.
  return new fileapi::FileSystemOperation(
      dispatcher.Pass(), file_proxy, context);
}

bool CrosMountPointProvider::GetVirtualPath(const FilePath& filesystem_path,
                                           FilePath* virtual_path) {
  for (MountPointMap::const_iterator iter = mount_point_map_.begin();
       iter != mount_point_map_.end();
       ++iter) {
    FilePath mount_prefix = iter->second.Append(iter->first);
    *virtual_path = FilePath(iter->first);
    if (mount_prefix.AppendRelativePath(filesystem_path, virtual_path)) {
      return true;
    } else if (mount_prefix == filesystem_path) {
      FilePath root = FilePath(FILE_PATH_LITERAL("/"));
      *virtual_path = root.Append(iter->first);
      return true;
    }
  }
  return false;
}

}  // namespace chromeos
<commit_msg>[cros] Fix the GetVirtualPath to always return the path without leading slash (as expected by clients).<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/chromeos/fileapi/cros_mount_point_provider.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/utf_string_conversions.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFileSystem.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "webkit/chromeos/fileapi/file_access_permissions.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
#include "webkit/fileapi/file_system_operation.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/native_file_util.h"
#include "webkit/glue/webkit_glue.h"

namespace chromeos {

typedef struct {
  const char* local_root_path;
  const char* web_root_path;
} FixedExposedPaths;

const char kChromeUIScheme[] = "chrome";

// Top level file system elements exposed in FileAPI in ChromeOS:
FixedExposedPaths fixed_exposed_paths[] = {
    {"/home/chronos/user/", "Downloads"},
    {"/media",              "archive"},
    {"/media",              "removable"},
};

CrosMountPointProvider::CrosMountPointProvider(
    scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy)
    : special_storage_policy_(special_storage_policy),
      file_access_permissions_(new FileAccessPermissions()),
      local_file_util_(
          new fileapi::LocalFileUtil(new fileapi::NativeFileUtil())) {
  for (size_t i = 0; i < arraysize(fixed_exposed_paths); i++) {
    mount_point_map_.insert(std::pair<std::string, FilePath>(
        std::string(fixed_exposed_paths[i].web_root_path),
        FilePath(std::string(fixed_exposed_paths[i].local_root_path))));
  }
}

CrosMountPointProvider::~CrosMountPointProvider() {
}

// TODO(zelidrag) share with SandboxMountPointProvider impl.
std::string GetOriginIdentifierFromURL(
    const GURL& url) {
  WebKit::WebSecurityOrigin web_security_origin =
      WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
  return web_security_origin.databaseIdentifier().utf8();
}

bool CrosMountPointProvider::GetRootForVirtualPath(
    const FilePath& virtual_path, FilePath* root_path) {
  std::vector<FilePath::StringType> components;
  virtual_path.GetComponents(&components);
  if (components.size() < 1) {
    return false;
  }

  base::AutoLock locker(lock_);
  // Check if this root mount point is exposed by this provider.
  MountPointMap::iterator iter = mount_point_map_.find(components[0]);
  if (iter == mount_point_map_.end()) {
    return false;
  }
  *root_path = iter->second;
  return true;
}

void CrosMountPointProvider::ValidateFileSystemRoot(
    const GURL& origin_url,
    fileapi::FileSystemType type,
    bool create,
    const ValidateFileSystemCallback& callback) {
  // Nothing to validate for external filesystem.
  DCHECK(type == fileapi::kFileSystemTypeExternal);
  callback.Run(base::PLATFORM_FILE_OK);
}

FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread(
    const GURL& origin_url,
    fileapi::FileSystemType type,
    const FilePath& virtual_path,
    bool create) {
  DCHECK(type == fileapi::kFileSystemTypeExternal);
  FilePath root_path;
  if (!GetRootForVirtualPath(virtual_path, &root_path))
    return FilePath();

  return root_path;
}

bool CrosMountPointProvider::IsAccessAllowed(const GURL& origin_url,
                                             fileapi::FileSystemType type,
                                             const FilePath& virtual_path) {
  if (type != fileapi::kFileSystemTypeExternal)
    return false;

  // Permit access to mount points from internal WebUI.
  if (origin_url.SchemeIs(kChromeUIScheme))
    return true;

  std::string extension_id = origin_url.host();
  // Check first to make sure this extension has fileBrowserHander permissions.
  if (!special_storage_policy_->IsFileHandler(extension_id))
    return false;

  return file_access_permissions_->HasAccessPermission(extension_id,
                                                       virtual_path);
}

// TODO(zelidrag): Share this code with SandboxMountPointProvider impl.
bool CrosMountPointProvider::IsRestrictedFileName(const FilePath& path) const {
  return false;
}

void CrosMountPointProvider::AddMountPoint(FilePath mount_point) {
  base::AutoLock locker(lock_);
  mount_point_map_.erase(mount_point.BaseName().value());
  mount_point_map_.insert(std::pair<std::string, FilePath>(
      mount_point.BaseName().value(), mount_point.DirName()));
}

void CrosMountPointProvider::RemoveMountPoint(FilePath mount_point) {
  base::AutoLock locker(lock_);
  mount_point_map_.erase(mount_point.BaseName().value());
}

void CrosMountPointProvider::GrantFullAccessToExtension(
    const std::string& extension_id) {
  DCHECK(special_storage_policy_->IsFileHandler(extension_id));
  if (!special_storage_policy_->IsFileHandler(extension_id))
    return;
  for (MountPointMap::const_iterator iter = mount_point_map_.begin();
       iter != mount_point_map_.end();
       ++iter) {
    GrantFileAccessToExtension(extension_id, FilePath(iter->first));
  }
}

void CrosMountPointProvider::GrantFileAccessToExtension(
    const std::string& extension_id, const FilePath& virtual_path) {
  // All we care about here is access from extensions for now.
  DCHECK(special_storage_policy_->IsFileHandler(extension_id));
  if (!special_storage_policy_->IsFileHandler(extension_id))
    return;
  file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
}

void CrosMountPointProvider::RevokeAccessForExtension(
      const std::string& extension_id) {
  file_access_permissions_->RevokePermissions(extension_id);
}

std::vector<FilePath> CrosMountPointProvider::GetRootDirectories() const {
  std::vector<FilePath> root_dirs;
  for (MountPointMap::const_iterator iter = mount_point_map_.begin();
       iter != mount_point_map_.end();
       ++iter) {
    root_dirs.push_back(iter->second.Append(iter->first));
  }
  return root_dirs;
}

fileapi::FileSystemFileUtil* CrosMountPointProvider::GetFileUtil() {
  return local_file_util_.get();
}

fileapi::FileSystemOperationInterface*
CrosMountPointProvider::CreateFileSystemOperation(
    const GURL& origin_url,
    fileapi::FileSystemType file_system_type,
    const FilePath& virtual_path,
    scoped_ptr<fileapi::FileSystemCallbackDispatcher> dispatcher,
    base::MessageLoopProxy* file_proxy,
    fileapi::FileSystemContext* context) const {
  // TODO(satorux,zel): instantiate appropriate FileSystemOperation that
  // implements async/remote operations.
  return new fileapi::FileSystemOperation(
      dispatcher.Pass(), file_proxy, context);
}

bool CrosMountPointProvider::GetVirtualPath(const FilePath& filesystem_path,
                                           FilePath* virtual_path) {
  for (MountPointMap::const_iterator iter = mount_point_map_.begin();
       iter != mount_point_map_.end();
       ++iter) {
    FilePath mount_prefix = iter->second.Append(iter->first);
    *virtual_path = FilePath(iter->first);
    if (mount_prefix == filesystem_path) {
      return true;
    } else if (mount_prefix.AppendRelativePath(filesystem_path, virtual_path)) {
      return true;
    }
  }
  return false;
}

}  // namespace chromeos
<|endoftext|>


<commit_before>#include <iostream>
#include <iterator>
#include <algorithm>

#include "headings.h"
#include "libaps2.h"
#include "constants.h"
#include "concol.h"
#include "helpers.h"

#include "optionparser.h"

enum  optionIndex { UNKNOWN, HELP, WFA_FILE, WFB_FILE, TRIG_MODE, TRIG_INTERVAL, LOG_LEVEL};
const option::Descriptor usage[] =
{
	{UNKNOWN, 0,"" , ""    , option::Arg::None, "USAGE: play_waveform [options]\n\n"
	                                         "Options:" },
	{HELP,    0,"" , "help", option::Arg::None, "  --help  \tPrint usage and exit." },
	{WFA_FILE, 0,"", "wfA", option::Arg::Required, "  --wfA  \tChannel A waveform file (ASCII signed 16 bit integer)" },
	{WFB_FILE, 0,"", "wfB", option::Arg::Required, "  --wfB  \tChannel B waveform file (ASCII signed 16 bit integer)" },
	{TRIG_MODE, 0,"", "trigMode", option::Arg::Required, "  --trigMode  \tTrigger mode (0: external; 1: internal; 2: software" },
	{TRIG_INTERVAL,  0,"", "trigInterval", option::Arg::Numeric, "  --trigRep  \tInternal trigger interval" },
	{LOG_LEVEL,  0,"", "debugLevel", option::Arg::Numeric, "  --debugLevel  \tDebug level to print" },
	{UNKNOWN, 0,"" ,  ""   , option::Arg::None, "\nExamples:\n"
	                                         "  play_waveform --wfA=../examples/wfA.dat --wfB=../examples/wfB.dat\n"
	                                         "  play_waveform --wfA=../examples/wfB.dat --trigMode=2\n" },
	{0,0,0,0,0,0}
};

int main(int argc, char* argv[])
{
	argc-=(argc>0); argv+=(argc>0); // skip program name argv[0] if present
	option::Stats  stats(usage, argc, argv);
	option::Option options[stats.options_max], buffer[stats.buffer_max];
	option::Parser parse(usage, argc, argv, options, buffer);

	if (parse.error())
	 return -1;

	if (options[HELP] || argc == 0) {
	 option::printUsage(std::cout, usage);
	 return 0;
	}

	for (option::Option* opt = options[UNKNOWN]; opt; opt = opt->next())
	 std::cout << "Unknown option: " << opt->name << "\n";

	for (int i = 0; i < parse.nonOptionsCount(); ++i)
	 std::cout << "Non-option #" << i << ": " << parse.nonOption(i) << "\n";

	//Debug level
	int debugLevel = 4;
	if (options[LOG_LEVEL]) {
		debugLevel = atoi(options[LOG_LEVEL].arg);
	}

	//Trigger source -- default of internal
	int triggerSource = 1;
	if (options[TRIG_MODE]) {
		triggerSource = atoi(options[TRIG_MODE].arg);
	}

	//Trigger interval -- default of 10ms
	double trigInterval = 10e-3;
	if (options[TRIG_INTERVAL]) {
		trigInterval = atof(options[TRIG_INTERVAL].arg);
	}

	//Load the waveform files
	vector<int16_t> wfA, wfB;
	std::ifstream ifs;
	if (options[WFA_FILE]) {
		ifs.open(std::string(options[WFA_FILE].arg));
		std::copy(std::istream_iterator<int16_t>(ifs), std::istream_iterator<int16_t>(), std::back_inserter(wfA) );
	}

	if (options[WFB_FILE]) {
		ifs.open(std::string(options[WFB_FILE].arg));
		std::copy(std::istream_iterator<int16_t>(ifs), std::istream_iterator<int16_t>(), std::back_inserter(wfB) );
	}

	//Pad the waveforms so they are the same size
	size_t longestLength = std::max(wfA.size(), wfB.size());
	wfA.resize(longestLength, 0);
	wfB.resize(longestLength, 0);

	string deviceSerial = get_device_id();

	set_logging_level(debugLevel);
	set_log("stdout");

	connect_APS(deviceSerial.c_str());

	double uptime = get_uptime(deviceSerial.c_str());

	cout << concol::RED << "Uptime for device " << deviceSerial << " is " << uptime << " seconds" << concol::RESET << endl;

	// force initialize device
	initAPS(deviceSerial.c_str(), 1);

	//load the waveforms
	set_waveform_int(deviceSerial.c_str(), 0, wfA.data(), wfA.size());
	set_waveform_int(deviceSerial.c_str(), 1, wfB.data(), wfB.size());

	//Set the trigger mode
	set_trigger_source(deviceSerial.c_str(), triggerSource);

	//Trigger interval
	set_trigger_interval(deviceSerial.c_str(), trigInterval);

	//Set to triggered waveform mode
	set_run_mode(deviceSerial.c_str(), 1);

	run(deviceSerial.c_str());

	//For software trigger, trigger on key stroke
	std::string charIn;
	if (triggerSource == 2) {
		std::cout << "Return to trigger or enter `q` to quit";
		getline(cin, charIn);
		while(charIn != "q") {
			if (charIn == "t"){
				trigger(deviceSerial.c_str());
			}
			getline(cin, charIn);
		}
		std::cout << std::endl;
	}
	else {
		std::cout << "Enter `q` to quit";
		getline(cin, charIn);
		while(cin >> charIn) {
			if (charIn == "q") {
				break;
			}
			getline(cin, charIn);
		}
		std::cout << std::endl;
	}

	stop(deviceSerial.c_str());

	return 0;
 }<commit_msg>Add interrupt handling.<commit_after>#include <iostream>
#include <iterator>
#include <algorithm>
#include <signal.h>

#include "headings.h"
#include "libaps2.h"
#include "constants.h"
#include "concol.h"
#include "helpers.h"

#include "optionparser.h"

enum  optionIndex { UNKNOWN, HELP, WFA_FILE, WFB_FILE, TRIG_MODE, TRIG_INTERVAL, LOG_LEVEL};
const option::Descriptor usage[] =
{
	{UNKNOWN, 0,"" , ""    , option::Arg::None, "USAGE: play_waveform [options]\n\n"
	                                         "Options:" },
	{HELP,    0,"" , "help", option::Arg::None, "  --help  \tPrint usage and exit." },
	{WFA_FILE, 0,"", "wfA", option::Arg::Required, "  --wfA  \tChannel A waveform file (ASCII signed 16 bit integer)" },
	{WFB_FILE, 0,"", "wfB", option::Arg::Required, "  --wfB  \tChannel B waveform file (ASCII signed 16 bit integer)" },
	{TRIG_MODE, 0,"", "trigMode", option::Arg::Required, "  --trigMode  \tTrigger mode (0: external; 1: internal; 2: software" },
	{TRIG_INTERVAL,  0,"", "trigInterval", option::Arg::Numeric, "  --trigRep  \tInternal trigger interval" },
	{LOG_LEVEL,  0,"", "debugLevel", option::Arg::Numeric, "  --debugLevel  \tDebug level to print" },
	{UNKNOWN, 0,"" ,  ""   , option::Arg::None, "\nExamples:\n"
	                                         "  play_waveform --wfA=../examples/wfA.dat --wfB=../examples/wfB.dat\n"
	                                         "  play_waveform --wfA=../examples/wfB.dat --trigMode=2\n" },
	{0,0,0,0,0,0}
};

static string deviceSerial;

void clean_up(int sigValue){
	std::cout << std::endl;
	stop(deviceSerial.c_str());
	disconnect_APS(deviceSerial.c_str());
	exit(1);
}

int main(int argc, char* argv[])
{
	argc-=(argc>0); argv+=(argc>0); // skip program name argv[0] if present
	option::Stats  stats(usage, argc, argv);
	option::Option options[stats.options_max], buffer[stats.buffer_max];
	option::Parser parse(usage, argc, argv, options, buffer);

	if (parse.error())
	 return -1;

	if (options[HELP] || argc == 0) {
	 option::printUsage(std::cout, usage);
	 return 0;
	}

	for (option::Option* opt = options[UNKNOWN]; opt; opt = opt->next())
	 std::cout << "Unknown option: " << opt->name << "\n";

	for (int i = 0; i < parse.nonOptionsCount(); ++i)
	 std::cout << "Non-option #" << i << ": " << parse.nonOption(i) << "\n";

	//Debug level
	int debugLevel = 4;
	if (options[LOG_LEVEL]) {
		debugLevel = atoi(options[LOG_LEVEL].arg);
	}

	//Trigger source -- default of internal
	int triggerSource = 1;
	if (options[TRIG_MODE]) {
		triggerSource = atoi(options[TRIG_MODE].arg);
	}

	//Trigger interval -- default of 10ms
	double trigInterval = 10e-3;
	if (options[TRIG_INTERVAL]) {
		trigInterval = atof(options[TRIG_INTERVAL].arg);
	}

	//Load the waveform files
	vector<int16_t> wfA, wfB;
	std::ifstream ifs;
	if (options[WFA_FILE]) {
		ifs.open(std::string(options[WFA_FILE].arg));
		std::copy(std::istream_iterator<int16_t>(ifs), std::istream_iterator<int16_t>(), std::back_inserter(wfA) );
	}

	if (options[WFB_FILE]) {
		ifs.open(std::string(options[WFB_FILE].arg));
		std::copy(std::istream_iterator<int16_t>(ifs), std::istream_iterator<int16_t>(), std::back_inserter(wfB) );
	}

	//Pad the waveforms so they are the same size
	size_t longestLength = std::max(wfA.size(), wfB.size());
	wfA.resize(longestLength, 0);
	wfB.resize(longestLength, 0);

	deviceSerial = get_device_id();

	set_logging_level(debugLevel);
	set_log("stdout");

	connect_APS(deviceSerial.c_str());

	double uptime = get_uptime(deviceSerial.c_str());

	cout << concol::RED << "Uptime for device " << deviceSerial << " is " << uptime << " seconds" << concol::RESET << endl;

	// force initialize device
	initAPS(deviceSerial.c_str(), 1);

	//load the waveforms
	set_waveform_int(deviceSerial.c_str(), 0, wfA.data(), wfA.size());
	set_waveform_int(deviceSerial.c_str(), 1, wfB.data(), wfB.size());

	//Set the trigger mode
	set_trigger_source(deviceSerial.c_str(), triggerSource);

	//Trigger interval
	set_trigger_interval(deviceSerial.c_str(), trigInterval);

	//Set to triggered waveform mode
	set_run_mode(deviceSerial.c_str(), 1);

	run(deviceSerial.c_str());

	//Catch ctrl-c to clean_up the APS -- see http://zguide.zeromq.org/cpp:interrupt
	struct sigaction action;
	action.sa_handler = clean_up;
	action.sa_flags = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);

	//For software trigger, trigger on key stroke
	if (triggerSource == 2) {
		std::cout << "Return to trigger or ctrl-c to exit";
		while(true) {
			cin.get();
			cout << "Got something!";
			trigger(deviceSerial.c_str());
		}
		std::cout << std::endl;
	}
	else {
		std::cout << "Ctrl-c to quit";
		while(true) {
			cin.get();
			cout << "Got something!";
		}
	}

	return 0;
 }<|endoftext|>