<commit_before>/*=========================================================================

  Program:   Visualization Library
  Module:    DSMapper.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Methods to map abstract DataSet through concrete mappers.
//
#include "DSMapper.hh"
#include "PolyMap.hh"

vlDataSetMapper::vlDataSetMapper()
{
  this->Input = NULL;
  this->GeometryExtractor = NULL;
  this->PolyMapper = NULL;
}

vlDataSetMapper::~vlDataSetMapper()
{
  if ( this->Input )
    {
    this->Input->UnRegister(this);
    }

  if ( this->GeometryExtractor )
    {
    this->GeometryExtractor->UnRegister(this);
    }

  if ( this->PolyMapper )
    {
    this->PolyMapper->UnRegister(this);
    }
}

void vlDataSetMapper::SetInput(vlDataSet *in)
{
  if (in != this->Input )
    {
    this->Input = in;
    this->Input->Register(this);
    this->Modified();
    }
}
vlDataSet* vlDataSetMapper::GetInput()
{
  return this->Input;
}

//
// Return bounding box of data
//
float *vlDataSetMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->Input )
    return bounds;
  else
    {
    this->Input->Update();
    return this->Input->GetBounds();
    }
}
//
// Receives from Actor -> maps data to primitives
//
void vlDataSetMapper::Render(vlRenderer *ren)
{
//
// make sure that we've been properly initialized
//
  if ( !this->Input )
    {
    vlErrorMacro(<< "No input!\n");
    return;
    }
//
// Now can create appropriate mapper
//
  if ( this->PolyMapper == NULL )
    {
    vlGeometryFilter *gf = new vlGeometryFilter();
    vlPolyMapper *pm = new vlPolyMapper;
    pm->SetInput(gf);

    this->GeometryExtractor = gf;
    this->GeometryExtractor->Register(this);

    this->PolyMapper = pm;
    this->PolyMapper->Register(this);
    }

  // update ourselves in case something has changed
  this->PolyMapper->SetLookupTable(this->GetLookupTable());
  this->PolyMapper->SetScalarsVisible(this->GetScalarsVisible());
  this->PolyMapper->SetScalarRange(this->GetScalarRange());

  this->GeometryExtractor->SetInput(this->Input);
  this->PolyMapper->Render(ren);

}

void vlDataSetMapper::PrintSelf(ostream& os, vlIndent indent)
{
  if (this->ShouldIPrint(vlDataSetMapper::GetClassName()))
    {
    vlMapper::PrintSelf(os,indent);

    if ( this->Input )
      {
      os << indent << "Input: (" << this->Input << ")\n";
      }
    else
      {
      os << indent << "Input: (none)\n";
      }

    if ( this->PolyMapper )
      {
      os << indent << "Poly Mapper: (" << this->PolyMapper << ")\n";
      }
    else
      {
      os << indent << "Poly Mapper: (none)\n";
      }

    if ( this->GeometryExtractor )
      {
      os << indent << "Geometry Extractor: (" << this->GeometryExtractor << ")\n";
      }
    else
      {
      os << indent << "Geometry Extractor: (none)\n";
      }
   }
}
<commit_msg>ENH: Create lookup table when necessary.<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    DSMapper.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Methods to map abstract DataSet through concrete mappers.
//
#include "DSMapper.hh"
#include "PolyMap.hh"

vlDataSetMapper::vlDataSetMapper()
{
  this->Input = NULL;
  this->GeometryExtractor = NULL;
  this->PolyMapper = NULL;
}

vlDataSetMapper::~vlDataSetMapper()
{
  if ( this->Input )
    {
    this->Input->UnRegister(this);
    }

  if ( this->GeometryExtractor )
    {
    this->GeometryExtractor->UnRegister(this);
    }

  if ( this->PolyMapper )
    {
    this->PolyMapper->UnRegister(this);
    }
}

void vlDataSetMapper::SetInput(vlDataSet *in)
{
  if (in != this->Input )
    {
    this->Input = in;
    this->Input->Register(this);
    this->Modified();
    }
}
vlDataSet* vlDataSetMapper::GetInput()
{
  return this->Input;
}

//
// Return bounding box of data
//
float *vlDataSetMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->Input )
    return bounds;
  else
    {
    this->Input->Update();
    return this->Input->GetBounds();
    }
}
//
// Receives from Actor -> maps data to primitives
//
void vlDataSetMapper::Render(vlRenderer *ren)
{
//
// make sure that we've been properly initialized
//
  if ( !this->Input )
    {
    vlErrorMacro(<< "No input!\n");
    return;
    }
//
// Need a lookup table
//
  if ( ! this->LookupTable ) this->SetLookupTable(new vlLookupTable);
  this->LookupTable->Build();
//
// Now can create appropriate mapper
//
  if ( this->PolyMapper == NULL )
    {
    vlGeometryFilter *gf = new vlGeometryFilter();
    vlPolyMapper *pm = new vlPolyMapper;
    pm->SetInput(gf);

    this->GeometryExtractor = gf;
    this->GeometryExtractor->Register(this);

    this->PolyMapper = pm;
    this->PolyMapper->Register(this);
    }

  // update ourselves in case something has changed
  this->PolyMapper->SetLookupTable(this->GetLookupTable());
  this->PolyMapper->SetScalarsVisible(this->GetScalarsVisible());
  this->PolyMapper->SetScalarRange(this->GetScalarRange());

  this->GeometryExtractor->SetInput(this->Input);
  this->PolyMapper->Render(ren);

}

void vlDataSetMapper::PrintSelf(ostream& os, vlIndent indent)
{
  if (this->ShouldIPrint(vlDataSetMapper::GetClassName()))
    {
    vlMapper::PrintSelf(os,indent);

    if ( this->Input )
      {
      os << indent << "Input: (" << this->Input << ")\n";
      }
    else
      {
      os << indent << "Input: (none)\n";
      }

    if ( this->PolyMapper )
      {
      os << indent << "Poly Mapper: (" << this->PolyMapper << ")\n";
      }
    else
      {
      os << indent << "Poly Mapper: (none)\n";
      }

    if ( this->GeometryExtractor )
      {
      os << indent << "Geometry Extractor: (" << this->GeometryExtractor << ")\n";
      }
    else
      {
      os << indent << "Geometry Extractor: (none)\n";
      }
   }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * 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.
 */

#define LOG_TAG "JNIHelp"

#include "JniConstants.h"
#include "JNIHelp.h"
#include "ALog-priv.h"

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

#include <string>

/**
 * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
 */
template<typename T>
class scoped_local_ref {
public:
    scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
    : mEnv(env), mLocalRef(localRef)
    {
    }

    ~scoped_local_ref() {
        reset();
    }

    void reset(T localRef = NULL) {
        if (mLocalRef != NULL) {
            (*mEnv)->DeleteLocalRef(reinterpret_cast<JNIEnv*>(mEnv), mLocalRef);
            mLocalRef = localRef;
        }
    }

    T get() const {
        return mLocalRef;
    }

private:
    C_JNIEnv* mEnv;
    T mLocalRef;

    // Disallow copy and assignment.
    scoped_local_ref(const scoped_local_ref&);
    void operator=(const scoped_local_ref&);
};

static jclass findClass(C_JNIEnv* env, const char* className) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    return (*env)->FindClass(e, className);
}

extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
    const JNINativeMethod* gMethods, int numMethods)
{
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    ALOGV("Registering %s's %d native methods...", className, numMethods);

    scoped_local_ref<jclass> c(env, findClass(env, className));
    if (c.get() == NULL) {
        char* msg;
        asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className);
        e->FatalError(msg);
    }

    if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
        char* msg;
        asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
        e->FatalError(msg);
    }

    return 0;
}

/*
 * Returns a human-readable summary of an exception object.  The buffer will
 * be populated with the "binary" class name and, if present, the
 * exception message.
 */
static bool getExceptionSummary(C_JNIEnv* env, jthrowable exception, std::string& result) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    /* get the name of the exception's class */
    scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
    scoped_local_ref<jclass> classClass(env,
            (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail
    jmethodID classGetNameMethod =
            (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;");
    scoped_local_ref<jstring> classNameStr(env,
            (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod));
    if (classNameStr.get() == NULL) {
        (*env)->ExceptionClear(e);
        result = "<error getting class name>";
        return false;
    }
    const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL);
    if (classNameChars == NULL) {
        (*env)->ExceptionClear(e);
        result = "<error getting class name UTF-8>";
        return false;
    }
    result += classNameChars;
    (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars);

    /* if the exception has a detail message, get that */
    jmethodID getMessage =
            (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;");
    scoped_local_ref<jstring> messageStr(env,
            (jstring) (*env)->CallObjectMethod(e, exception, getMessage));
    if (messageStr.get() == NULL) {
        return true;
    }

    result += ": ";

    const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
    if (messageChars != NULL) {
        result += messageChars;
        (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars);
    } else {
        result += "<error getting message>";
        (*env)->ExceptionClear(e); // clear OOM
    }

    return true;
}

/*
 * Returns an exception (with stack trace) as a string.
 */
static bool getStackTrace(C_JNIEnv* env, jthrowable exception, std::string& result) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    scoped_local_ref<jclass> stringWriterClass(env, findClass(env, "java/io/StringWriter"));
    if (stringWriterClass.get() == NULL) {
        return false;
    }

    jmethodID stringWriterCtor = (*env)->GetMethodID(e, stringWriterClass.get(), "<init>", "()V");
    jmethodID stringWriterToStringMethod =
            (*env)->GetMethodID(e, stringWriterClass.get(), "toString", "()Ljava/lang/String;");

    scoped_local_ref<jclass> printWriterClass(env, findClass(env, "java/io/PrintWriter"));
    if (printWriterClass.get() == NULL) {
        return false;
    }

    jmethodID printWriterCtor =
            (*env)->GetMethodID(e, printWriterClass.get(), "<init>", "(Ljava/io/Writer;)V");

    scoped_local_ref<jobject> stringWriter(env,
            (*env)->NewObject(e, stringWriterClass.get(), stringWriterCtor));
    if (stringWriter.get() == NULL) {
        return false;
    }

    jobject printWriter =
            (*env)->NewObject(e, printWriterClass.get(), printWriterCtor, stringWriter.get());
    if (printWriter == NULL) {
        return false;
    }

    scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
    jmethodID printStackTraceMethod =
            (*env)->GetMethodID(e, exceptionClass.get(), "printStackTrace", "(Ljava/io/PrintWriter;)V");
    (*env)->CallVoidMethod(e, exception, printStackTraceMethod, printWriter);

    if ((*env)->ExceptionCheck(e)) {
        return false;
    }

    scoped_local_ref<jstring> messageStr(env,
            (jstring) (*env)->CallObjectMethod(e, stringWriter.get(), stringWriterToStringMethod));
    if (messageStr.get() == NULL) {
        return false;
    }

    const char* utfChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
    if (utfChars == NULL) {
        return false;
    }

    result = utfChars;

    (*env)->ReleaseStringUTFChars(e, messageStr.get(), utfChars);
    return true;
}

extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    if ((*env)->ExceptionCheck(e)) {
        /* TODO: consider creating the new exception with this as "cause" */
        scoped_local_ref<jthrowable> exception(env, (*env)->ExceptionOccurred(e));
        (*env)->ExceptionClear(e);

        if (exception.get() != NULL) {
            std::string text;
            getExceptionSummary(env, exception.get(), text);
            ALOGW("Discarding pending exception (%s) to throw %s", text.c_str(), className);
        }
    }

    scoped_local_ref<jclass> exceptionClass(env, findClass(env, className));
    if (exceptionClass.get() == NULL) {
        ALOGE("Unable to find exception class %s", className);
        /* ClassNotFoundException now pending */
        return -1;
    }

    if ((*env)->ThrowNew(e, exceptionClass.get(), msg) != JNI_OK) {
        ALOGE("Failed throwing '%s' '%s'", className, msg);
        /* an exception, most likely OOM, will now be pending */
        return -1;
    }

    return 0;
}

int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) {
    char msgBuf[512];
    vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
    return jniThrowException(env, className, msgBuf);
}

int jniThrowNullPointerException(C_JNIEnv* env, const char* msg) {
    return jniThrowException(env, "java/lang/NullPointerException", msg);
}

int jniThrowRuntimeException(C_JNIEnv* env, const char* msg) {
    return jniThrowException(env, "java/lang/RuntimeException", msg);
}

int jniThrowIOException(C_JNIEnv* env, int errnum) {
    char buffer[80];
    const char* message = jniStrError(errnum, buffer, sizeof(buffer));
    return jniThrowException(env, "java/io/IOException", message);
}

static std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    scoped_local_ref<jthrowable> currentException(env, (*env)->ExceptionOccurred(e));
    if (exception == NULL) {
        exception = currentException.get();
        if (exception == NULL) {
          return "<no pending exception>";
        }
    }

    if (currentException.get() != NULL) {
        (*env)->ExceptionClear(e);
    }

    std::string trace;
    if (!getStackTrace(env, exception, trace)) {
        (*env)->ExceptionClear(e);
        getExceptionSummary(env, exception, trace);
    }

    if (currentException.get() != NULL) {
        (*env)->Throw(e, currentException.get()); // rethrow
    }

    return trace;
}

void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception) {
    std::string trace(jniGetStackTrace(env, exception));
    __android_log_write(priority, tag, trace.c_str());
}

const char* jniStrError(int errnum, char* buf, size_t buflen) {
#if __GLIBC__
    // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int.
    // char *strerror_r(int errnum, char *buf, size_t n);
    return strerror_r(errnum, buf, buflen);
#else
    int rc = strerror_r(errnum, buf, buflen);
    if (rc != 0) {
        // (POSIX only guarantees a value other than 0. The safest
        // way to implement this function is to use C++ and overload on the
        // type of strerror_r to accurately distinguish GNU from POSIX.)
        snprintf(buf, buflen, "errno %d", errnum);
    }
    return buf;
#endif
}

jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jmethodID ctor = e->GetMethodID(JniConstants::fileDescriptorClass, "<init>", "()V");
    jobject fileDescriptor = (*env)->NewObject(e, JniConstants::fileDescriptorClass, ctor);
    // NOTE: NewObject ensures that an OutOfMemoryError will be seen by the Java
    // caller if the alloc fails, so we just return NULL when that happens.
    if (fileDescriptor != NULL)  {
        jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
    }
    return fileDescriptor;
}

int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
    if (fileDescriptor != NULL) {
        return (*env)->GetIntField(e, fileDescriptor, fid);
    } else {
        return -1;
    }
}

void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
    (*env)->SetIntField(e, fileDescriptor, fid, value);
}

jobject jniGetReferent(C_JNIEnv* env, jobject ref) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jmethodID get = e->GetMethodID(JniConstants::referenceClass, "get", "()Ljava/lang/Object;");
    return (*env)->CallObjectMethod(e, ref, get);
}
<commit_msg>asprintfが無い環境のビルドを修正 refs #1<commit_after>/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * 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.
 */

#define LOG_TAG "JNIHelp"

#include "JniConstants.h"
#include "JNIHelp.h"
#include "ALog-priv.h"

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

#include <string>

/**
 * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
 */
template<typename T>
class scoped_local_ref {
public:
    scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
    : mEnv(env), mLocalRef(localRef)
    {
    }

    ~scoped_local_ref() {
        reset();
    }

    void reset(T localRef = NULL) {
        if (mLocalRef != NULL) {
            (*mEnv)->DeleteLocalRef(reinterpret_cast<JNIEnv*>(mEnv), mLocalRef);
            mLocalRef = localRef;
        }
    }

    T get() const {
        return mLocalRef;
    }

private:
    C_JNIEnv* mEnv;
    T mLocalRef;

    // Disallow copy and assignment.
    scoped_local_ref(const scoped_local_ref&);
    void operator=(const scoped_local_ref&);
};

static jclass findClass(C_JNIEnv* env, const char* className) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    return (*env)->FindClass(e, className);
}

extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
    const JNINativeMethod* gMethods, int numMethods)
{
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    ALOGV("Registering %s's %d native methods...", className, numMethods);

    scoped_local_ref<jclass> c(env, findClass(env, className));
    if (c.get() == NULL) {
#ifdef __MINGW32__
        char msg[512] = "";
        sprintf(msg, "Native registration unable to find class '%s'; aborting...", className);
#else
        char* msg;
        asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className);
#endif /* __MINGW32__ */
        e->FatalError(msg);
    }

    if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
#ifdef __MINGW32__
        char msg[512] = "";
        sprintf(msg, "RegisterNatives failed for '%s'; aborting...", className);
#else
        char* msg;
        asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
#endif /* __MINGW32__ */
        e->FatalError(msg);
    }

    return 0;
}

/*
 * Returns a human-readable summary of an exception object.  The buffer will
 * be populated with the "binary" class name and, if present, the
 * exception message.
 */
static bool getExceptionSummary(C_JNIEnv* env, jthrowable exception, std::string& result) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    /* get the name of the exception's class */
    scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
    scoped_local_ref<jclass> classClass(env,
            (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail
    jmethodID classGetNameMethod =
            (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;");
    scoped_local_ref<jstring> classNameStr(env,
            (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod));
    if (classNameStr.get() == NULL) {
        (*env)->ExceptionClear(e);
        result = "<error getting class name>";
        return false;
    }
    const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL);
    if (classNameChars == NULL) {
        (*env)->ExceptionClear(e);
        result = "<error getting class name UTF-8>";
        return false;
    }
    result += classNameChars;
    (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars);

    /* if the exception has a detail message, get that */
    jmethodID getMessage =
            (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;");
    scoped_local_ref<jstring> messageStr(env,
            (jstring) (*env)->CallObjectMethod(e, exception, getMessage));
    if (messageStr.get() == NULL) {
        return true;
    }

    result += ": ";

    const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
    if (messageChars != NULL) {
        result += messageChars;
        (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars);
    } else {
        result += "<error getting message>";
        (*env)->ExceptionClear(e); // clear OOM
    }

    return true;
}

/*
 * Returns an exception (with stack trace) as a string.
 */
static bool getStackTrace(C_JNIEnv* env, jthrowable exception, std::string& result) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    scoped_local_ref<jclass> stringWriterClass(env, findClass(env, "java/io/StringWriter"));
    if (stringWriterClass.get() == NULL) {
        return false;
    }

    jmethodID stringWriterCtor = (*env)->GetMethodID(e, stringWriterClass.get(), "<init>", "()V");
    jmethodID stringWriterToStringMethod =
            (*env)->GetMethodID(e, stringWriterClass.get(), "toString", "()Ljava/lang/String;");

    scoped_local_ref<jclass> printWriterClass(env, findClass(env, "java/io/PrintWriter"));
    if (printWriterClass.get() == NULL) {
        return false;
    }

    jmethodID printWriterCtor =
            (*env)->GetMethodID(e, printWriterClass.get(), "<init>", "(Ljava/io/Writer;)V");

    scoped_local_ref<jobject> stringWriter(env,
            (*env)->NewObject(e, stringWriterClass.get(), stringWriterCtor));
    if (stringWriter.get() == NULL) {
        return false;
    }

    jobject printWriter =
            (*env)->NewObject(e, printWriterClass.get(), printWriterCtor, stringWriter.get());
    if (printWriter == NULL) {
        return false;
    }

    scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
    jmethodID printStackTraceMethod =
            (*env)->GetMethodID(e, exceptionClass.get(), "printStackTrace", "(Ljava/io/PrintWriter;)V");
    (*env)->CallVoidMethod(e, exception, printStackTraceMethod, printWriter);

    if ((*env)->ExceptionCheck(e)) {
        return false;
    }

    scoped_local_ref<jstring> messageStr(env,
            (jstring) (*env)->CallObjectMethod(e, stringWriter.get(), stringWriterToStringMethod));
    if (messageStr.get() == NULL) {
        return false;
    }

    const char* utfChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
    if (utfChars == NULL) {
        return false;
    }

    result = utfChars;

    (*env)->ReleaseStringUTFChars(e, messageStr.get(), utfChars);
    return true;
}

extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    if ((*env)->ExceptionCheck(e)) {
        /* TODO: consider creating the new exception with this as "cause" */
        scoped_local_ref<jthrowable> exception(env, (*env)->ExceptionOccurred(e));
        (*env)->ExceptionClear(e);

        if (exception.get() != NULL) {
            std::string text;
            getExceptionSummary(env, exception.get(), text);
            ALOGW("Discarding pending exception (%s) to throw %s", text.c_str(), className);
        }
    }

    scoped_local_ref<jclass> exceptionClass(env, findClass(env, className));
    if (exceptionClass.get() == NULL) {
        ALOGE("Unable to find exception class %s", className);
        /* ClassNotFoundException now pending */
        return -1;
    }

    if ((*env)->ThrowNew(e, exceptionClass.get(), msg) != JNI_OK) {
        ALOGE("Failed throwing '%s' '%s'", className, msg);
        /* an exception, most likely OOM, will now be pending */
        return -1;
    }

    return 0;
}

int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) {
    char msgBuf[512];
    vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
    return jniThrowException(env, className, msgBuf);
}

int jniThrowNullPointerException(C_JNIEnv* env, const char* msg) {
    return jniThrowException(env, "java/lang/NullPointerException", msg);
}

int jniThrowRuntimeException(C_JNIEnv* env, const char* msg) {
    return jniThrowException(env, "java/lang/RuntimeException", msg);
}

int jniThrowIOException(C_JNIEnv* env, int errnum) {
    char buffer[80];
    const char* message = jniStrError(errnum, buffer, sizeof(buffer));
    return jniThrowException(env, "java/io/IOException", message);
}

static std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);

    scoped_local_ref<jthrowable> currentException(env, (*env)->ExceptionOccurred(e));
    if (exception == NULL) {
        exception = currentException.get();
        if (exception == NULL) {
          return "<no pending exception>";
        }
    }

    if (currentException.get() != NULL) {
        (*env)->ExceptionClear(e);
    }

    std::string trace;
    if (!getStackTrace(env, exception, trace)) {
        (*env)->ExceptionClear(e);
        getExceptionSummary(env, exception, trace);
    }

    if (currentException.get() != NULL) {
        (*env)->Throw(e, currentException.get()); // rethrow
    }

    return trace;
}

void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception) {
    std::string trace(jniGetStackTrace(env, exception));
    __android_log_write(priority, tag, trace.c_str());
}

const char* jniStrError(int errnum, char* buf, size_t buflen) {
#if __GLIBC__
    // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int.
    // char *strerror_r(int errnum, char *buf, size_t n);
    return strerror_r(errnum, buf, buflen);
#else
    int rc = strerror_r(errnum, buf, buflen);
    if (rc != 0) {
        // (POSIX only guarantees a value other than 0. The safest
        // way to implement this function is to use C++ and overload on the
        // type of strerror_r to accurately distinguish GNU from POSIX.)
        snprintf(buf, buflen, "errno %d", errnum);
    }
    return buf;
#endif
}

jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jmethodID ctor = e->GetMethodID(JniConstants::fileDescriptorClass, "<init>", "()V");
    jobject fileDescriptor = (*env)->NewObject(e, JniConstants::fileDescriptorClass, ctor);
    // NOTE: NewObject ensures that an OutOfMemoryError will be seen by the Java
    // caller if the alloc fails, so we just return NULL when that happens.
    if (fileDescriptor != NULL)  {
        jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
    }
    return fileDescriptor;
}

int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
    if (fileDescriptor != NULL) {
        return (*env)->GetIntField(e, fileDescriptor, fid);
    } else {
        return -1;
    }
}

void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
    (*env)->SetIntField(e, fileDescriptor, fid, value);
}

jobject jniGetReferent(C_JNIEnv* env, jobject ref) {
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    static jmethodID get = e->GetMethodID(JniConstants::referenceClass, "get", "()Ljava/lang/Object;");
    return (*env)->CallObjectMethod(e, ref, get);
}
<|endoftext|>


<commit_before>#include "Player.h"
#include "Song.h"
#include "Pattern.h"
#include "ITrackState.h"
#include "PatternRow.h"
#include "SequenceRow.h"
#include "Sequence.h"
#include "Macro.h"
#include "SDL.h"
#include <cstdio>

IPlayer::IPlayer(Song& song)
	: Lockable(), mSong(song), state()
{
	trackState = new ITrackState*[SequenceRow::maxTracks];
}

IPlayer::~IPlayer()
{
	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
		delete trackState[i];

	delete[] trackState;
}

void IPlayer::reset()
{
	state = PlayerState();
}

void IPlayer::handleMacroTick(int track)
{
	handleMacroNote(track);

	ITrackState& trState = *trackState[track];

	if (trState.tick == 0)
	{
		int tries = 0;

		/*
		If the effect forces reprocessing, do this max. 2 times to prevent infinite loops with Jxx etc.
		*/

		while ((trState.macroState.handleEffectZeroTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).note, trState, state) ||
			trState.macroState.handleEffectZeroTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).effect, trState, state)) && tries < 2)
		{
			handleMacroNote(track);
			tries++;
		}
	}

	trState.macroState.handleEffectAnyTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).note, trState, state);
	trState.macroState.handleEffectAnyTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).effect, trState, state);
}

void IPlayer::advanceSequenceRow()
{
	state.patternRow = 0;
	state.setUpdated(PlayerState::Updated::SequenceRow|PlayerState::Updated::PatternRow);

	if (state.shouldAdvanceSequenceRow())
	{
		state.sequenceRow++;
		if (state.sequenceRow >= mSong.getSequenceLength())
			state.sequenceRow = 0;
	}
}

void IPlayer::advancePatternRow()
{
	++state.patternRow;
	state.setUpdated(PlayerState::Updated::PatternRow);

	if (state.patternRow >= mSong.getPatternLength())
	{
		advanceSequenceRow();
	}
}

void IPlayer::advanceTrackTick(int track)
{
	ITrackState& trState = *trackState[track];

	++trState.tick;

	if (trState.tick >= trState.macroSpeed)
	{
		trState.macroRow++;

		if (trState.macroRow >= Macro::maxMacroLength)
		{
			trState.macroRow = 0;
		}

		trState.tick = 0;
	}
}

void IPlayer::advanceSequenceTick()
{
	++state.tick;

	if (state.tick >= state.songSpeed)
	{
		if (processLastTick())
		{
			advancePatternRow();
		}

		state.tick = 0;
	}
}

void IPlayer::runTick()
{
	if (state.isPlaying())
	{
		handleNoteOn();
	}

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		handleMacroTick(i);
	}

	if (state.isPlaying())
	{
		if (state.tick == 0)
			processZeroTick();

		processAnyTick();
	}
}

void IPlayer::advanceTick()
{
	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
		advanceTrackTick(i);

	if (state.isPlaying())
		advanceSequenceTick();
}

void IPlayer::handleNoteOn()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	if (state.tick == 0)
	{
		for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
		{
			PatternRow& patternRow = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow);
			int note = patternRow.getNoteWithOctave();

			if (note != PatternRow::NoNote)
			{
				if (patternRow.effect.effect != '3')
				{
					if (patternRow.effect.effect == 'm')
						trackState[i]->macro = patternRow.effect.getParamsAsByte();

					triggerNote(i, note);
				}
				else
				{
					trackState[i]->trackState.setSlideTargetFromNote(note);
				}
			}
		}
	}
}

void IPlayer::handleMacroNote(int track)
{
	ITrackState& trState = *trackState[track];

	if (trState.tick == 0)
	{
		int note = mSong.getMacro(trState.macro).getRow(trState.macroRow).getNoteWithOctave();

		if (note != PatternRow::NoNote)
		{
			trState.macroState.setFrequencyFromNote(note - 3);
		}
	}
}

void IPlayer::triggerNoteWithReset(int track, int note, int macro)
{
	if (macro != -1)
		trackState[track]->macro = macro;

	triggerNote(track, note);
	state.tick = 0;
}

void IPlayer::triggerNote(int track, int note)
{
	ITrackState& trState = *trackState[track];
	trState.triggered = true;
	trState.trackState.setFrequencyFromNote(note);
	trState.tick = 0;
	trState.trackState.volume = ITrackState::maxVolume;
	trState.macroState.frequency = 1.0f;
	trState.macroState.volume = ITrackState::maxVolume;
	trState.macroRow = 0;
	trState.macroSpeed = 1;
	handleMacroTick(track);
}

void IPlayer::triggerNote(int track, const PatternRow& row)
{
	int note = row.getNoteWithOctave();

	if (note != PatternRow::NoNote)
	{
		triggerNote(track, note);
		state.tick = 0;
		processZeroTick(track, row);
		handleMacroTick(track);
	}
}

void IPlayer::processZeroTick(int track, const PatternRow& row)
{
	ITrackState& trState = *trackState[track];

	trState.trackState.handleEffectZeroTick(row.note, trState, state);
	trState.trackState.handleEffectZeroTick(row.effect, trState, state);
}

void IPlayer::processZeroTick()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		PatternRow&	row = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow);

		processZeroTick(i, row);
	}
}

void IPlayer::processAnyTick()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		ITrackState& trState = *trackState[i];
		PatternRow&	row = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow);
		trState.trackState.handleEffectAnyTick(row.note, trState, state);
		trState.trackState.handleEffectAnyTick(row.effect, trState, state);
	}
}

bool IPlayer::processLastTick()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		const EffectParam& effect = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow).effect;
		switch (effect.effect)
		{
			case 'b':
				advanceSequenceRow();
				state.sequenceRow = effect.getParamsAsByte();
				return false;

			case 'd':
				advanceSequenceRow();
				state.patternRow = effect.getParamsAsByte();
				return false;

		}
	}

	return true;
}

void IPlayer::setSequenceRow(int row)
{
	state.sequenceRow = row;
	state.setUpdated(PlayerState::Updated::SequenceRow);
}

void IPlayer::setPatternRow(int row)
{
	state.patternRow = row;
	state.setUpdated(PlayerState::Updated::PatternRow);
}

PlayerState& IPlayer::getPlayerState()
{
	return state;
}

ITrackState& IPlayer::getTrackState(int track)
{
	return *trackState[track];
}

void IPlayer::play(int sequenceRow)
{
	play(sequenceRow, PlayerState::Play);
}

void IPlayer::play(int sequenceRow, int mode)
{
	state.setUpdated(PlayerState::Updated::SequenceRow|PlayerState::Updated::PatternRow);
	muteTracks();
	state.sequenceRow = sequenceRow;
	state.patternRow = 0;
	state.tick = 0;
	state.mode = static_cast<PlayerState::Mode>(mode);
	runTick();
}

void IPlayer::stop()
{
	state.mode = PlayerState::Stop;
	muteTracks();
}

void IPlayer::muteTracks()
{
	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		ITrackState& trState = *trackState[i];
		trState.trackState.volume = 0;
	}
}

int IPlayer::getTick() const
{
	return state.tick;
}
<commit_msg>Playing a note during song playback should not interfere with timing<commit_after>#include "Player.h"
#include "Song.h"
#include "Pattern.h"
#include "ITrackState.h"
#include "PatternRow.h"
#include "SequenceRow.h"
#include "Sequence.h"
#include "Macro.h"
#include "SDL.h"
#include <cstdio>

IPlayer::IPlayer(Song& song)
	: Lockable(), mSong(song), state()
{
	trackState = new ITrackState*[SequenceRow::maxTracks];
}

IPlayer::~IPlayer()
{
	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
		delete trackState[i];

	delete[] trackState;
}

void IPlayer::reset()
{
	state = PlayerState();
}

void IPlayer::handleMacroTick(int track)
{
	handleMacroNote(track);

	ITrackState& trState = *trackState[track];

	if (trState.tick == 0)
	{
		int tries = 0;

		/*
		If the effect forces reprocessing, do this max. 2 times to prevent infinite loops with Jxx etc.
		*/

		while ((trState.macroState.handleEffectZeroTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).note, trState, state) ||
			trState.macroState.handleEffectZeroTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).effect, trState, state)) && tries < 2)
		{
			handleMacroNote(track);
			tries++;
		}
	}

	trState.macroState.handleEffectAnyTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).note, trState, state);
	trState.macroState.handleEffectAnyTick(mSong.getMacro(trState.macro).getRow(trState.macroRow).effect, trState, state);
}

void IPlayer::advanceSequenceRow()
{
	state.patternRow = 0;
	state.setUpdated(PlayerState::Updated::SequenceRow|PlayerState::Updated::PatternRow);

	if (state.shouldAdvanceSequenceRow())
	{
		state.sequenceRow++;
		if (state.sequenceRow >= mSong.getSequenceLength())
			state.sequenceRow = 0;
	}
}

void IPlayer::advancePatternRow()
{
	++state.patternRow;
	state.setUpdated(PlayerState::Updated::PatternRow);

	if (state.patternRow >= mSong.getPatternLength())
	{
		advanceSequenceRow();
	}
}

void IPlayer::advanceTrackTick(int track)
{
	ITrackState& trState = *trackState[track];

	++trState.tick;

	if (trState.tick >= trState.macroSpeed)
	{
		trState.macroRow++;

		if (trState.macroRow >= Macro::maxMacroLength)
		{
			trState.macroRow = 0;
		}

		trState.tick = 0;
	}
}

void IPlayer::advanceSequenceTick()
{
	++state.tick;

	if (state.tick >= state.songSpeed)
	{
		if (processLastTick())
		{
			advancePatternRow();
		}

		state.tick = 0;
	}
}

void IPlayer::runTick()
{
	if (state.isPlaying())
	{
		handleNoteOn();
	}

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		handleMacroTick(i);
	}

	if (state.isPlaying())
	{
		if (state.tick == 0)
			processZeroTick();

		processAnyTick();
	}
}

void IPlayer::advanceTick()
{
	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
		advanceTrackTick(i);

	if (state.isPlaying())
		advanceSequenceTick();
}

void IPlayer::handleNoteOn()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	if (state.tick == 0)
	{
		for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
		{
			PatternRow& patternRow = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow);
			int note = patternRow.getNoteWithOctave();

			if (note != PatternRow::NoNote)
			{
				if (patternRow.effect.effect != '3')
				{
					if (patternRow.effect.effect == 'm')
						trackState[i]->macro = patternRow.effect.getParamsAsByte();

					triggerNote(i, note);
				}
				else
				{
					trackState[i]->trackState.setSlideTargetFromNote(note);
				}
			}
		}
	}
}

void IPlayer::handleMacroNote(int track)
{
	ITrackState& trState = *trackState[track];

	if (trState.tick == 0)
	{
		int note = mSong.getMacro(trState.macro).getRow(trState.macroRow).getNoteWithOctave();

		if (note != PatternRow::NoNote)
		{
			trState.macroState.setFrequencyFromNote(note - 3);
		}
	}
}

void IPlayer::triggerNoteWithReset(int track, int note, int macro)
{
	if (macro != -1)
		trackState[track]->macro = macro;

	triggerNote(track, note);

	if (!state.isPlaying())
		state.tick = 0;
}

void IPlayer::triggerNote(int track, int note)
{
	ITrackState& trState = *trackState[track];
	trState.triggered = true;
	trState.trackState.setFrequencyFromNote(note);
	trState.tick = 0;
	trState.trackState.volume = ITrackState::maxVolume;
	trState.macroState.frequency = 1.0f;
	trState.macroState.volume = ITrackState::maxVolume;
	trState.macroRow = 0;
	trState.macroSpeed = 1;
	handleMacroTick(track);
}

void IPlayer::triggerNote(int track, const PatternRow& row)
{
	int note = row.getNoteWithOctave();

	if (note != PatternRow::NoNote)
	{
		triggerNote(track, note);
		state.tick = 0;
		processZeroTick(track, row);
		handleMacroTick(track);
	}
}

void IPlayer::processZeroTick(int track, const PatternRow& row)
{
	ITrackState& trState = *trackState[track];

	trState.trackState.handleEffectZeroTick(row.note, trState, state);
	trState.trackState.handleEffectZeroTick(row.effect, trState, state);
}

void IPlayer::processZeroTick()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		PatternRow&	row = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow);

		processZeroTick(i, row);
	}
}

void IPlayer::processAnyTick()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		ITrackState& trState = *trackState[i];
		PatternRow&	row = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow);
		trState.trackState.handleEffectAnyTick(row.note, trState, state);
		trState.trackState.handleEffectAnyTick(row.effect, trState, state);
	}
}

bool IPlayer::processLastTick()
{
	const SequenceRow& seqRow = mSong.getSequence().getRow(state.sequenceRow);

	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		const EffectParam& effect = mSong.getPattern(seqRow.pattern[i]).getRow(state.patternRow).effect;
		switch (effect.effect)
		{
			case 'b':
				advanceSequenceRow();
				state.sequenceRow = effect.getParamsAsByte();
				return false;

			case 'd':
				advanceSequenceRow();
				state.patternRow = effect.getParamsAsByte();
				return false;

		}
	}

	return true;
}

void IPlayer::setSequenceRow(int row)
{
	state.sequenceRow = row;
	state.setUpdated(PlayerState::Updated::SequenceRow);
}

void IPlayer::setPatternRow(int row)
{
	state.patternRow = row;
	state.setUpdated(PlayerState::Updated::PatternRow);
}

PlayerState& IPlayer::getPlayerState()
{
	return state;
}

ITrackState& IPlayer::getTrackState(int track)
{
	return *trackState[track];
}

void IPlayer::play(int sequenceRow)
{
	play(sequenceRow, PlayerState::Play);
}

void IPlayer::play(int sequenceRow, int mode)
{
	state.setUpdated(PlayerState::Updated::SequenceRow|PlayerState::Updated::PatternRow);
	muteTracks();
	state.sequenceRow = sequenceRow;
	state.patternRow = 0;
	state.tick = 0;
	state.mode = static_cast<PlayerState::Mode>(mode);
	runTick();
}

void IPlayer::stop()
{
	state.mode = PlayerState::Stop;
	muteTracks();
}

void IPlayer::muteTracks()
{
	for (int i = 0 ; i < SequenceRow::maxTracks ; ++i)
	{
		ITrackState& trState = *trackState[i];
		trState.trackState.volume = 0;
	}
}

int IPlayer::getTick() const
{
	return state.tick;
}
<|endoftext|>


<commit_before>// Chemfiles, a modern library for chemistry file reading and writing
// Copyright (C) 2015-2016 Guillaume Fraux and contributors
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

#include <algorithm>

#include "chemfiles/files/BasicFile.hpp"
#include "chemfiles/Error.hpp"
using namespace chemfiles;

BasicFile::BasicFile(const std::string& filename, File::Mode mode)
    : TextFile(filename, mode) {
    std::ios_base::openmode openmode;

    switch (mode) {
    case File::READ:
        openmode = std::ios_base::in;
        break;
    case File::APPEND:
        openmode = std::ios_base::out | std::ios_base::app;
        break;
    case File::WRITE:
        openmode = std::ios_base::out | std::ios_base::trunc;
        break;
    default:
        throw FileError(std::string("Got a bad file mode: ") + static_cast<char>(mode));
    }

    stream_.open(filename, openmode);
    if (!stream_.is_open()) {
        throw FileError("Could not open the file " + filename);
    }
    TextFile::rdbuf(stream_.rdbuf());
    rewind();
    stream_.clear();
    // Throw exceptions on errors
    stream_.exceptions(std::fstream::badbit | std::fstream::failbit);
}

std::string BasicFile::readline() {
    std::string line;
    try {
        std::getline(stream_, line);
    } catch (const std::ios_base::failure&) {
        throw FileError("Could not read a line in " + filename());
    }
    return line;
}

void BasicFile::rewind() {
    stream_.clear();
    stream_.seekg(0, std::ios::beg);
}

bool BasicFile::eof() {
    return stream_.eof();
}

std::vector<std::string> BasicFile::readlines(size_t n) {
    auto lines = std::vector<std::string>(n);
    for (size_t i = 0; i < n; i++) {
        try {
            std::getline(stream_, lines[i]);
        } catch (const std::ios_base::failure&) {
            throw FileError("Could not read lines in " + filename());
        }
    }
    return lines;
}
<commit_msg>Handle all possible line ending markers<commit_after>// Chemfiles, a modern library for chemistry file reading and writing
// Copyright (C) 2015-2016 Guillaume Fraux and contributors
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

#include <algorithm>

#include "chemfiles/files/BasicFile.hpp"
#include "chemfiles/Error.hpp"
using namespace chemfiles;

/// Read a single line from `stream` in `string`, handling all possible end of
/// line markers (`\n`, `\r`, `\r\n`).
///
/// Code from http://stackoverflow.com/a/6089413
static inline std::istream& get_line(std::istream& istream, std::string& string) {
    string.clear();

    // The characters in the stream are read one-by-one using a std::streambuf.
    // That is faster than reading them one-by-one using the std::istream.
    // Code that uses streambuf this way must be guarded by a sentry object.
    // The sentry object performs various tasks,
    // such as thread synchronization and updating the stream state.
    std::istream::sentry sentry(istream, true);
    std::streambuf* buffer = istream.rdbuf();

    while(true) {
        int c = buffer->sbumpc();
        switch (c) {
        case '\n':
            return istream;
        case '\r':
            if(buffer->sgetc() == '\n')
                buffer->sbumpc();
            return istream;
        case EOF:
            // Also handle the case when the last line has no line ending
            if(string.empty()) {
                istream.setstate(std::ios::eofbit);
            }
            return istream;
        default:
            string += static_cast<char>(c);
        }
    }
}

BasicFile::BasicFile(const std::string& filename, File::Mode mode)
    : TextFile(filename, mode) {
    std::ios_base::openmode openmode;

    switch (mode) {
    case File::READ:
        openmode = std::ios_base::in;
        break;
    case File::APPEND:
        openmode = std::ios_base::out | std::ios_base::app;
        break;
    case File::WRITE:
        openmode = std::ios_base::out | std::ios_base::trunc;
        break;
    default:
        throw FileError(std::string("Got a bad file mode: ") + static_cast<char>(mode));
    }

    stream_.open(filename, openmode);
    if (!stream_.is_open()) {
        throw FileError("Could not open the file " + filename);
    }
    TextFile::rdbuf(stream_.rdbuf());
    rewind();
    stream_.clear();
    // Throw exceptions on errors
    stream_.exceptions(std::fstream::badbit | std::fstream::failbit);
}

std::string BasicFile::readline() {
    std::string line;
    try {
        get_line(stream_, line);
    } catch (const std::ios_base::failure&) {
        throw FileError("Could not read a line in " + filename());
    }
    return line;
}

void BasicFile::rewind() {
    stream_.clear();
    stream_.seekg(0, std::ios::beg);
}

bool BasicFile::eof() {
    return stream_.eof();
}

std::vector<std::string> BasicFile::readlines(size_t n) {
    auto lines = std::vector<std::string>(n);
    for (size_t i = 0; i < n; i++) {
        try {
            get_line(stream_, lines[i]);
        } catch (const std::ios_base::failure&) {
            throw FileError("Could not read lines in " + filename());
        }
    }
    return lines;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2013 "Naftoreiclag" https://github.com/Naftoreiclag
 *
 * Distributed under the MIT License (http://opensource.org/licenses/mit-license.html)
 * See accompanying file LICENSE
 */

#include "util/Sysout.h"

#include "Game.h"

#include "Luastuff.h"

#include "Potato.h"

// Print lua errors (Gee, this place is becoming a mess...)
void printLuaErrors(lua_State* luaState, int luaScript)
{
    // Print the error message
    Sysout::println(lua_tostring(luaState, -1));

    // Removes that error message
    lua_pop(luaState, 1);
}

// Initialize
void initialize()
{
    // Set the display width to 80 chars long (for word-wrap)
    Sysout::setDisplayWidth(80);

    // If we are in debug mode, then print that
    #ifdef DEBUG
    Sysout::println("Running in DEBUG mode!");
    Sysout::printDictionaryEntries();
    #endif
}

// Run
void run()
{
    bool running = true;

    while(running)
    {
        // Put a title screen here

        // Run a game
        Game* game = new Game();
        game->load();
        game->run();
        delete game;
    }
}

// Finalize
void finalize()
{

}

int main()
{
    Potato potato;

    lua_State* luaState;
    luaState = luaL_newstate();

    luaL_openlibs(luaState);

    potato.luaify(luaState);

    int luaScript = luaL_dofile(luaState, "potatoProp.lua");

    printLuaErrors(luaState, luaScript);

    Sysout::println(potato.tastiness);
    Sysout::println(potato.bounciness);

    // Initialize
    initialize();

    // Run
    run();

    // Clean-up
    finalize();

    // Died quietly
    return 0;
}
<commit_msg>Fixed printLuaErrors() crashing if no errors<commit_after>/* Copyright (c) 2013 "Naftoreiclag" https://github.com/Naftoreiclag
 *
 * Distributed under the MIT License (http://opensource.org/licenses/mit-license.html)
 * See accompanying file LICENSE
 */

#include "util/Sysout.h"

#include "Game.h"

#include "Luastuff.h"

#include "Potato.h"

#include <iostream>

// Print lua errors (Gee, this place is becoming a mess...)
void printLuaErrors(lua_State* luaState, int luaScript)
{
    // Does something
    if(luaScript != 0)
    {
        // Print the error message
        std::cout << lua_tostring(luaState, -1) << std::endl;

        // Removes that error message
        lua_pop(luaState, 1);
    }
}

// Initialize
void initialize()
{
    // Set the display width to 80 chars long (for word-wrap)
    Sysout::setDisplayWidth(80);

    // If we are in debug mode, then print that
    #ifdef DEBUG
    Sysout::println("Running in DEBUG mode!");
    Sysout::printDictionaryEntries();
    #endif
}

// Run
void run()
{
    bool running = true;

    while(running)
    {
        // Put a title screen here

        // Run a game
        Game* game = new Game();
        game->load();
        game->run();
        delete game;
    }
}

// Finalize
void finalize()
{

}

int main()
{
    Potato potato;

    lua_State* luaState;
    luaState = luaL_newstate();

    luaL_openlibs(luaState);

    potato.luaify(luaState);

    int luaScript = luaL_dofile(luaState, "../bin/potatoProp.lua");

    printLuaErrors(luaState, luaScript);

    Sysout::println(potato.tastiness);
    Sysout::println(potato.bounciness);

    // Initialize
    initialize();

    // Run
    run();

    // Clean-up
    finalize();

    // Died quietly
    return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <sstream>

#include "liblogger.h"

namespace liblogger
{

LogTail::LogTail(size_t length)
{
	m_length = length;
}

void LogTail::GetName(std::string *str)
{
	*str = "Tail";
}

void LogTail::GetDesc(std::string *str)
{
	*str = "Keeps Last 'n' Messages in memory";
}

void LogTail::Log(const LogType Type, const std::string &str)
{
	if (m_data.size() >= m_length)
		m_data.pop_front();
	m_data.push_back(str);
}

std::string LogTail::GetData()
{
	std::list<std::string>::iterator it = m_data.begin();
	std::stringstream ss;
	while(it != m_data.end())
	{
		ss << *it << '\n';
		it++;
	}
	return ss.str();
}

};

<commit_msg>Fix Race in LogTail::GetData<commit_after>#include <stdio.h>
#include <sstream>

#include "liblogger.h"

namespace liblogger
{

LogTail::LogTail(size_t length)
{
	m_length = length;
}

void LogTail::GetName(std::string *str)
{
	*str = "Tail";
}

void LogTail::GetDesc(std::string *str)
{
	*str = "Keeps Last 'n' Messages in memory";
}

void LogTail::Log(const LogType Type, const std::string &str)
{
	if (m_data.size() >= m_length)
		m_data.pop_front();
	m_data.push_back(str);
}

std::string LogTail::GetData()
{
	LogManager::Lock();
	std::list<std::string>::iterator it = m_data.begin();
	std::stringstream ss;
	while(it != m_data.end())
	{
		ss << *it << '\n';
		it++;
	}
	LogManager::Unlock();
	return ss.str();
}

};

<|endoftext|>


<commit_before>#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "physics/solar_system.hpp"

namespace principia {

using astronomy::ICRFJ2000Equator;

namespace physics {

    class EclipseTest : public testing::Test {
    protected:
        EclipseTest() {
			solar_system_1950_.Initialize(
				SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
				SOLUTION_DIR / "astronomy" / "initial_state_jd_2433282_500000000.proto.txt");
		}

		SolarSystem<ICRFJ2000Equator> solar_system_1950_;
    };

    TEST_F(EclipseTest, Dummy){
        // ...
    };

} // physics

} // principia
<commit_msg>Almost a compiling test.<commit_after>#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "physics/solar_system.hpp"
#include "quantities/quantities.hpp"
#include "quantities/si.hpp"
#include "integrators/symplectic_runge_kutta_nyström_integrator.hpp"
#include "geometry/epoch.hpp"

namespace principia {

using astronomy::ICRFJ2000Equator;
using geometry::JulianDate;
using integrators::McLachlanAtela1992Order5Optimal;

namespace physics {

    class EclipseTest : public testing::Test {
    protected:
        EclipseTest() {
			solar_system_1950_.Initialize(
				SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
				SOLUTION_DIR / "astronomy" / "initial_state_jd_2433282_500000000.proto.txt");
		}

		SolarSystem<ICRFJ2000Equator> solar_system_1950_;
    };

    TEST_F(EclipseTest, Dummy) {
        auto ephemeris = solar_system_1950_.MakeEphemeris(McLachlanAtela1992Order5Optimal<Position<ICRFJ000Equator>>(),
		45 * Minute,
		5 * Milli(Metre));

		ephemeris->Prolong(JulianDate(2433374.5));
		// Prolong until date of eclipse
		// pass body to Ephemeris.trajectory
    };

} // physics

} // principia
<|endoftext|>


<commit_before>#include "geometry/epoch.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/grassmann.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "integrators/symplectic_runge_kutta_nyström_integrator.hpp"
#include "physics/solar_system.hpp"
#include "quantities/elementary_functions.hpp"
#include "quantities/quantities.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/numerics.hpp"

namespace principia {

using astronomy::ICRFJ2000Equator;
using geometry::JulianDate;
using geometry::Sign;
using integrators::McLachlanAtela1992Order5Optimal;
using quantities::ArcCos;
using quantities::si::Kilo;
using quantities::si::Metre;
using quantities::si::Milli;
using quantities::si::Minute;
using quantities::si::Nano;
using testing_utilities::AbsoluteError;
using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

namespace physics {

class EclipseTest : public testing::Test {
 protected:
  EclipseTest() {
    solar_system_1950_.Initialize(
        SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
        SOLUTION_DIR / "astronomy" /
            "initial_state_jd_2433282_500000000.proto.txt");
  }

  void CheckLunarEclipse(Instant const& current_time,
                         Sign const moon_offset_sign) {
    auto ephemeris = solar_system_1950_.MakeEphemeris(
        McLachlanAtela1992Order5Optimal<Position<ICRFJ2000Equator>>(),
        45 * Minute, 5 * Milli(Metre));

    ephemeris->Prolong(
        JulianDate(2433374.5));  // Prolong just past date of eclipse
                                 // (Eclipse was 1950-04-02 but JD
                                 // is 1950-04-03 00:00:00).
    auto const sun = solar_system_1950_.massive_body(*ephemeris, "Sun");
    auto const earth = solar_system_1950_.massive_body(*ephemeris, "Earth");
    auto const moon = solar_system_1950_.massive_body(*ephemeris, "Moon");

    auto const q_sun = ephemeris->trajectory(sun)
                           ->EvaluatePosition(current_time, /*hint=*/nullptr);
    auto const q_moon = ephemeris->trajectory(moon)
                            ->EvaluatePosition(current_time, /*hint=*/nullptr);
    auto const q_earth = ephemeris->trajectory(earth)
                             ->EvaluatePosition(current_time, /*hint=*/nullptr);

    // MassiveBody will need radius information.  Or non-hardcoded data from
    // https://github.com/mockingbirdnest/Principia/blob/master/astronomy/gravity_model.proto.txt
    auto const r_sun = 696000.0 * Kilo(Metre);
    auto const r_earth = 6378.1363 * Kilo(Metre);
    auto const r_moon = 1738.0 * Kilo(Metre);

    // Checking body angles at the target time.
    // Angle formed by a right circular cone with sides defined by tangent lines
    // between Sun and Earth, and axis running through the centers of each.
    auto const half_sun_earth_aperture =
        ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
    auto const q_U = q_earth +
                     Normalize(q_earth - q_sun) *
                         (r_earth + moon_offset_sign * r_moon) /
                         Sin(half_sun_earth_aperture);
    // Angle between Earth and Moon as seen at q_U.
    auto const earth_moon_angle =
        ArcCos(InnerProduct(q_U - q_earth, q_U - q_moon) /
               ((q_U - q_moon).Norm() * (q_U - q_earth).Norm()));
    // We are at the desired contact if the angle between Earth and Moon from
    // the apex of the umbra (Earth-Sun cone) matches the half-aperture of said
    // cone.
    EXPECT_THAT(AbsoluteError(half_sun_earth_aperture, earth_moon_angle),
                AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
        << NAMED(half_sun_earth_aperture) << ", " << NAMED(earth_moon_angle)
        << ", " << NAMED(current_time);
    return;
  }

  SolarSystem<ICRFJ2000Equator> solar_system_1950_;
};

TEST_F(EclipseTest, Dummy) {
  // Dates are TDB Julian Day for 1948-04-02.
  auto const P1 = JulianDate(2433374.25788409);  // 18:10:49 UT
  auto const U1 = JulianDate(2433374.29850909);  // 19:09:19
  auto const U2 = JulianDate(2433374.354979);    // 20:30:38
  auto const U3 = JulianDate(2433374.37367113);  // 20:57:33
  auto const U4 = JulianDate(2433374.43016419);  // 22:18:54
  auto const P4 = JulianDate(2433374.47075446);  // 23:17:21

  Sign const U14 = Sign(1);
  Sign const U23 = Sign(-1);
  CheckLunarEclipse(U1, U14);
  CheckLunarEclipse(U2, U23);
  CheckLunarEclipse(U3, U23);
  CheckLunarEclipse(U4, U14);

  // Later on for additional accuracy: 2 * ArcTan((x_norm_y -
  // y_normx).Norm(),(x_norm_y + y_norm_x).Norm())
  // x_norm_y = x * y.Norm() and y_norm_x = y * x.Norm()

  // Future: check 2048-01-01 Lunar eclipse.
  // P1 = 03:52:39 UT
  // U1 = 05:05:17 UT
  // U2 = 06:24:27
  // U3 = 07:20:23
  // U4 = 08:39:33
  // P4 = 09:52:05
  // etimes = {2469076.66235167, 2469076.71279148, 2469076.76776833,
  // 2469076.80661092, 2469076.86158778, 2469076.91195815};
}

}  // namespace physics
}  // namespace principia
<commit_msg>Identify yourself. You have 15 seconds to comply.<commit_after>#include "geometry/epoch.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/grassmann.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "integrators/symplectic_runge_kutta_nyström_integrator.hpp"
#include "physics/solar_system.hpp"
#include "quantities/elementary_functions.hpp"
#include "quantities/quantities.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/numerics.hpp"

namespace principia {

using astronomy::ICRFJ2000Equator;
using geometry::JulianDate;
using geometry::Sign;
using integrators::McLachlanAtela1992Order5Optimal;
using quantities::ArcCos;
using quantities::si::Kilo;
using quantities::si::Metre;
using quantities::si::Milli;
using quantities::si::Minute;
using quantities::si::Nano;
using testing_utilities::AbsoluteError;
using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

namespace physics {

class EclipseTest : public testing::Test {
 protected:
  EclipseTest() {
    solar_system_1950_.Initialize(
        SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
        SOLUTION_DIR / "astronomy" /
            "initial_state_jd_2433282_500000000.proto.txt");
  }

  void CheckLunarEclipse(Instant const& current_time,
                         Sign const moon_offset_sign) {
    auto ephemeris = solar_system_1950_.MakeEphemeris(
        McLachlanAtela1992Order5Optimal<Position<ICRFJ2000Equator>>(),
        45 * Minute, 5 * Milli(Metre));

    ephemeris->Prolong(
        JulianDate(2433374.5));  // Prolong just past date of eclipse
                                 // (Eclipse was 1950-04-02 but JD
                                 // is 1950-04-03 00:00:00).
    auto const sun = solar_system_1950_.massive_body(*ephemeris, "Sun");
    auto const earth = solar_system_1950_.massive_body(*ephemeris, "Earth");
    auto const moon = solar_system_1950_.massive_body(*ephemeris, "Moon");

    auto const q_sun = ephemeris->trajectory(sun)
                           ->EvaluatePosition(current_time, /*hint=*/nullptr);
    auto const q_moon = ephemeris->trajectory(moon)
                            ->EvaluatePosition(current_time, /*hint=*/nullptr);
    auto const q_earth = ephemeris->trajectory(earth)
                             ->EvaluatePosition(current_time, /*hint=*/nullptr);

    // MassiveBody will need radius information.  Or non-hardcoded data from
    // https://github.com/mockingbirdnest/Principia/blob/master/astronomy/gravity_model.proto.txt
    auto const r_sun = 696000.0 * Kilo(Metre);
    auto const r_earth = 6378.1363 * Kilo(Metre);
    auto const r_moon = 1738.0 * Kilo(Metre);

    // Checking body angles at the target time.
    // Angle formed by a right circular cone with sides defined by tangent lines
    // between Sun and Earth, and axis running through the centers of each.
    auto const umbral_half_aperture =
        ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
    auto const apex_of_moon_locus_at_umbral_contact =
        q_earth +
        Normalize(q_earth - q_sun) * (r_earth + moon_offset_sign * r_moon) /
            Sin(umbral_half_aperture);
    // Angle between Earth and Moon as seen at
    // apex_of_moon_locus_at_umbral_contact.
    auto const earth_moon_angle =
        ArcCos(InnerProduct(apex_of_moon_locus_at_umbral_contact - q_earth,
                            apex_of_moon_locus_at_umbral_contact - q_moon) /
               ((apex_of_moon_locus_at_umbral_contact - q_moon).Norm() *
                (apex_of_moon_locus_at_umbral_contact - q_earth).Norm()));
    // We are at the desired contact if the angle between Earth and Moon from
    // the apex of the umbra (Earth-Sun cone) is the same value (though offset
    // from) the half-aperture of said cone.
    EXPECT_THAT(AbsoluteError(umbral_half_aperture, earth_moon_angle),
                AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
        << NAMED(umbral_half_aperture) << ", " << NAMED(earth_moon_angle)
        << ", " << NAMED(current_time);
    return;
  }

  SolarSystem<ICRFJ2000Equator> solar_system_1950_;
};

TEST_F(EclipseTest, Dummy) {
  // Dates are TDB Julian Day for 1948-04-02.
  auto const P1 = JulianDate(2433374.25788409);  // 18:10:49 UT
  auto const U1 = JulianDate(2433374.29850909);  // 19:09:19
  auto const U2 = JulianDate(2433374.354979);    // 20:30:38
  auto const U3 = JulianDate(2433374.37367113);  // 20:57:33
  auto const U4 = JulianDate(2433374.43016419);  // 22:18:54
  auto const P4 = JulianDate(2433374.47075446);  // 23:17:21

  Sign const U14 = Sign(1);
  Sign const U23 = Sign(-1);
  CheckLunarEclipse(U1, U14);
  CheckLunarEclipse(U2, U23);
  CheckLunarEclipse(U3, U23);
  CheckLunarEclipse(U4, U14);

  // Later on for additional accuracy: 2 * ArcTan((x_norm_y -
  // y_normx).Norm(),(x_norm_y + y_norm_x).Norm())
  // x_norm_y = x * y.Norm() and y_norm_x = y * x.Norm()

  // Future: check 2048-01-01 Lunar eclipse.
  // P1 = 03:52:39 UT
  // U1 = 05:05:17 UT
  // U2 = 06:24:27
  // U3 = 07:20:23
  // U4 = 08:39:33
  // P4 = 09:52:05
  // etimes = {2469076.66235167, 2469076.71279148, 2469076.76776833,
  // 2469076.80661092, 2469076.86158778, 2469076.91195815};
}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>#include "geometry/epoch.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/grassmann.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "integrators/symplectic_runge_kutta_nyström_integrator.hpp"
#include "physics/solar_system.hpp"
#include "quantities/elementary_functions.hpp"
#include "quantities/quantities.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/numerics.hpp"

namespace principia {

using astronomy::ICRFJ2000Equator;
using geometry::JulianDate;
using integrators::McLachlanAtela1992Order5Optimal;
using quantities::ArcCos;
using quantities::si::Kilo;
using quantities::si::Metre;
using quantities::si::Milli;
using quantities::si::Minute;
using quantities::si::Nano;
using testing_utilities::AbsoluteError;
using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

namespace physics {

class EclipseTest : public testing::Test {
 protected:
  EclipseTest() {
    solar_system_1950_.Initialize(
        SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
        SOLUTION_DIR / "astronomy" /
            "initial_state_jd_2433282_500000000.proto.txt");
  }

  SolarSystem<ICRFJ2000Equator> solar_system_1950_;
};

TEST_F(EclipseTest, Dummy) {
  auto ephemeris = solar_system_1950_.MakeEphemeris(
      McLachlanAtela1992Order5Optimal<Position<ICRFJ2000Equator>>(),
      45 * Minute, 5 * Milli(Metre));

  ephemeris->Prolong(
      JulianDate(2433374.5));  // Prolong just past date of eclipse
                               // (Eclipse was 1950-04-02 but JD
                               // is 1950-04-03:00:00:00).
  // Pass body to Ephemeris.trajectory.
  auto const sun = solar_system_1950_.massive_body(*ephemeris, "Sun");
  auto const earth = solar_system_1950_.massive_body(*ephemeris, "Earth");
  auto const moon = solar_system_1950_.massive_body(*ephemeris, "Moon");

  // MassiveBody eventually needs radius information. Or non-hardcoded data from
  // https://github.com/mockingbirdnest/Principia/blob/master/astronomy/gravity_model.proto.txt
  auto const r_sun = 696000.0 * Kilo(Metre);
  auto const r_earth = 6378.1363 * Kilo(Metre);
  auto const r_moon = 1738.0 * Kilo(Metre);

  // Dates are TDB Julian Day for 1948-04-02.
  auto const P1 = JulianDate(2433374.25788409);  // 18:10:49 UT
  auto const U1 = JulianDate(2433374.29850909);  // 19:09:19
  auto const U2 = JulianDate(2433374.354979);    // 20:30:38
  auto const U3 = JulianDate(2433374.37367113);  // 20:57:33
  auto const U4 = JulianDate(2433374.43016419);  // 22:18:54
  auto const P4 = JulianDate(2433374.47075446);  // 23:17:21

  // Lunar eclipse -- U1 (time is start of umbral phase).
  auto q_sun = ephemeris->trajectory(sun)->EvaluatePosition(U1, nullptr);
  auto q_moon = ephemeris->trajectory(moon)->EvaluatePosition(U1, nullptr);
  auto q_earth = ephemeris->trajectory(earth)->EvaluatePosition(U1, nullptr);

  // Check body angles at target time.
  // Earth/Sun lineup.
  auto half_sun_earth_aperture =
      ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
  auto q_U14 = q_earth +
               Normalize(q_earth - q_sun) * (r_earth + r_moon) /
                   Sin(half_sun_earth_aperture);
  // Earth/Moon lineup for U14.
  auto half_earth_moon_aperture =
      ArcCos(InnerProduct(q_U14 - q_earth, q_U14 - q_moon) /
             ((q_U14 - q_moon).Norm() * (q_U14 - q_earth).Norm()));
  // Do the angles work?
  EXPECT_THAT(AbsoluteError(half_sun_earth_aperture, half_earth_moon_aperture),
              AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
      << NAMED(half_sun_earth_aperture) << ", "
      << NAMED(half_earth_moon_aperture);

  // Lunar eclipse -- U2 (time is start of full eclipse).
  q_sun = ephemeris->trajectory(sun)->EvaluatePosition(U2, nullptr);
  q_moon = ephemeris->trajectory(moon)->EvaluatePosition(U2, nullptr);
  q_earth = ephemeris->trajectory(earth)->EvaluatePosition(U2, nullptr);

  // Check body angles at target time.
  // Earth/Sun lineup.
  half_sun_earth_aperture =
      ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
  auto q_U23 = q_earth +
               Normalize(q_earth - q_sun) * (r_earth - r_moon) /
                   Sin(half_sun_earth_aperture);
  // Earth/Moon lineup for U23.
  half_earth_moon_aperture =
      ArcCos(InnerProduct(q_U23 - q_earth, q_U23 - q_moon) /
             ((q_U23 - q_moon).Norm() * (q_U23 - q_earth).Norm()));
  // Do the angles work?
  EXPECT_THAT(AbsoluteError(half_sun_earth_aperture, half_earth_moon_aperture),
              AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
      << NAMED(half_sun_earth_aperture) << ", "
      << NAMED(half_earth_moon_aperture);

  // Lunar eclipse -- U3 (time is end of full eclipse).
  q_sun = ephemeris->trajectory(sun)->EvaluatePosition(U3, nullptr);
  q_moon = ephemeris->trajectory(moon)->EvaluatePosition(U3, nullptr);
  q_earth = ephemeris->trajectory(earth)->EvaluatePosition(U3, nullptr);

  // Check body angles at target time.
  // Earth/Sun lineup.
  half_sun_earth_aperture =
      ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
  q_U23 = q_earth +
          Normalize(q_earth - q_sun) * (r_earth - r_moon) /
              Sin(half_sun_earth_aperture);
  // Earth/Moon lineup for U23.
  half_earth_moon_aperture =
      ArcCos(InnerProduct(q_U23 - q_earth, q_U23 - q_moon) /
             ((q_U23 - q_moon).Norm() * (q_U23 - q_earth).Norm()));
  // Do the angles work?
  EXPECT_THAT(AbsoluteError(half_sun_earth_aperture, half_earth_moon_aperture),
              AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
      << NAMED(half_sun_earth_aperture) << ", "
      << NAMED(half_earth_moon_aperture);

  // Lunar eclipse -- U4 (time is end of umbral phase).
  q_sun = ephemeris->trajectory(sun)->EvaluatePosition(U4, nullptr);
  q_moon = ephemeris->trajectory(moon)->EvaluatePosition(U4, nullptr);
  q_earth = ephemeris->trajectory(earth)->EvaluatePosition(U4, nullptr);

  // Check body angles at target time.
  // Earth/Sun lineup.
  half_sun_earth_aperture =
      ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
  q_U14 = q_earth +
          Normalize(q_earth - q_sun) * (r_earth + r_moon) /
              Sin(half_sun_earth_aperture);
  // Earth/Moon lineup for U14.
  half_earth_moon_aperture =
      ArcCos(InnerProduct(q_U14 - q_earth, q_U14 - q_moon) /
             ((q_U14 - q_moon).Norm() * (q_U14 - q_earth).Norm()));
  // Do the angles work?
  EXPECT_THAT(AbsoluteError(half_sun_earth_aperture, half_earth_moon_aperture),
              AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
      << NAMED(half_sun_earth_aperture) << ", "
      << NAMED(half_earth_moon_aperture);

  // Later on for additional accuracy: 2 * ArcTan((x_norm_y -
  // y_normx).Norm(),(x_norm_y + y_norm_x).Norm())
  // x_norm_y = x * y.Norm() and y_norm_x = y * x.Norm()

  // Future: check 2048-01-01 Lunar eclipse.
  // P1 = 03:52:39 UT
  // U1 = 05:05:17 UT
  // U2 = 06:24:27
  // U3 = 07:20:23
  // U4 = 08:39:33
  // P4 = 09:52:05
  // etimes = {2469076.66235167, 2469076.71279148, 2469076.76776833,
  // 2469076.80661092, 2469076.86158778, 2469076.91195815};
}

}  // namespace physics
}  // namespace principia
<commit_msg>Second pass phl/egg review<commit_after>#include "geometry/epoch.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/grassmann.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "integrators/symplectic_runge_kutta_nyström_integrator.hpp"
#include "physics/solar_system.hpp"
#include "quantities/elementary_functions.hpp"
#include "quantities/quantities.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/numerics.hpp"

namespace principia {

using astronomy::ICRFJ2000Equator;
using geometry::JulianDate;
using geometry::Sign;
using integrators::McLachlanAtela1992Order5Optimal;
using quantities::ArcCos;
using quantities::si::Kilo;
using quantities::si::Metre;
using quantities::si::Milli;
using quantities::si::Minute;
using quantities::si::Nano;
using testing_utilities::AbsoluteError;
using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

namespace physics {

class EclipseTest : public testing::Test {
 protected:
  EclipseTest() {
    solar_system_1950_.Initialize(
        SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
        SOLUTION_DIR / "astronomy" /
            "initial_state_jd_2433282_500000000.proto.txt");
  }

  void CheckLunarEclipse(Instant const& current_time, Sign const moon_offset) {
    auto ephemeris = solar_system_1950_.MakeEphemeris(
        McLachlanAtela1992Order5Optimal<Position<ICRFJ2000Equator>>(),
        45 * Minute, 5 * Milli(Metre));

    ephemeris->Prolong(
        JulianDate(2433374.5));  // Prolong just past date of eclipse
                                 // (Eclipse was 1950-04-02 but JD
                                 // is 1950-04-03 00:00:00).
    auto const sun = solar_system_1950_.massive_body(*ephemeris, "Sun");
    auto const earth = solar_system_1950_.massive_body(*ephemeris, "Earth");
    auto const moon = solar_system_1950_.massive_body(*ephemeris, "Moon");

    auto const q_sun = ephemeris->trajectory(sun)->EvaluatePosition(
        current_time, /* hint= */ nullptr);
    auto const q_moon = ephemeris->trajectory(moon)->EvaluatePosition(
        current_time, /* hint= */ nullptr);
    auto const q_earth = ephemeris->trajectory(earth)->EvaluatePosition(
        current_time, /* hint= */ nullptr);

    // MassiveBody eventually needs radius information.
    // Or non-hardcoded data from
    // https://github.com/mockingbirdnest/Principia/blob/master/astronomy/gravity_model.proto.txt
    auto const r_sun = 696000.0 * Kilo(Metre);
    auto const r_earth = 6378.1363 * Kilo(Metre);
    auto const r_moon = 1738.0 * Kilo(Metre);

    // Check body angles at target time.
    // Earth/Sun lineup.
    auto half_sun_earth_aperture =
        ArcSin((r_sun - r_earth) / (q_sun - q_earth).Norm());
    auto q_U = q_earth;
    if (Sign(moon_offset).Positive()) {
      q_U += Normalize(q_earth - q_sun) * (r_earth + r_moon) /
             Sin(half_sun_earth_aperture);
    } else if (Sign(moon_offset).Negative()) {
      q_U += Normalize(q_earth - q_sun) * (r_earth - r_moon) /
             Sin(half_sun_earth_aperture);
    }
    // Earth/Moon lineup.
    auto half_earth_moon_aperture =
        ArcCos(InnerProduct(q_U - q_earth, q_U - q_moon) /
               ((q_U - q_moon).Norm() * (q_U - q_earth).Norm()));
    // Do the angles match up?
    EXPECT_THAT(
        AbsoluteError(half_sun_earth_aperture, half_earth_moon_aperture),
        AllOf(Lt(1.0 * Milli(Radian)), Gt(1.0 * Nano(Radian))))
        << NAMED(half_sun_earth_aperture) << ", "
        << NAMED(half_earth_moon_aperture) << ", " << NAMED(current_time);
    return;
  }

  SolarSystem<ICRFJ2000Equator> solar_system_1950_;
};

TEST_F(EclipseTest, Dummy) {
  // Dates are TDB Julian Day for 1948-04-02.
  auto const P1 = JulianDate(2433374.25788409);  // 18:10:49 UT
  auto const U1 = JulianDate(2433374.29850909);  // 19:09:19
  auto const U2 = JulianDate(2433374.354979);    // 20:30:38
  auto const U3 = JulianDate(2433374.37367113);  // 20:57:33
  auto const U4 = JulianDate(2433374.43016419);  // 22:18:54
  auto const P4 = JulianDate(2433374.47075446);  // 23:17:21

  Sign const U14 = Sign(1);
  Sign const U23 = Sign(-1);
  CheckLunarEclipse(U1, U14);
  CheckLunarEclipse(U2, U23);
  CheckLunarEclipse(U3, U23);
  CheckLunarEclipse(U4, U14);

  // Later on for additional accuracy: 2 * ArcTan((x_norm_y -
  // y_normx).Norm(),(x_norm_y + y_norm_x).Norm())
  // x_norm_y = x * y.Norm() and y_norm_x = y * x.Norm()

  // Future: check 2048-01-01 Lunar eclipse.
  // P1 = 03:52:39 UT
  // U1 = 05:05:17 UT
  // U2 = 06:24:27
  // U3 = 07:20:23
  // U4 = 08:39:33
  // P4 = 09:52:05
  // etimes = {2469076.66235167, 2469076.71279148, 2469076.76776833,
  // 2469076.80661092, 2469076.86158778, 2469076.91195815};
}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>#include "NTClient.h"
using namespace std;

NTClient::NTClient() {
	hasError = false;
	firstConnect = true;
	connected = false;
}
bool NTClient::login(string username, string password) {
	uname = username;
	pword = password;
	bool ret = true;
	string data = string("username=");
	data += uname;
	data += "&password=";
	data += pword;
	data += "&adb=1&tz=America%2FChicago"; // No need to have anything other than Chicago timezone
	httplib::SSLClient loginReq(NITROTYPE_HOSTNAME, HTTPS_PORT);
	shared_ptr<httplib::Response> res = loginReq.post(NT_LOGIN_ENDPOINT, data, "application/x-www-form-urlencoded; charset=UTF-8");
	if (res) {
		bool foundLoginCookie = false;
		for (int i = 0; i < res->cookies.size(); ++i) {
			string cookie = res->cookies.at(i);
			addCookie(Utils::extractCKey(cookie), Utils::extractCValue(cookie));
			if (cookie.find("ntuserrem=") == 0) {
				foundLoginCookie = true;
				token = Utils::extractCValue(cookie);
				cout << "Retrieved login token: " << token << endl;
				// addCookie("ntuserrem", token);
			}
		}
		if (!foundLoginCookie) {
			ret = false;
			cout << "Unable to locate the login cookie. Maybe try a different account?\n";
		}
	} else {
		ret = false;
		cout << "Login request failed. This might be a network issue. Maybe try resetting your internet connection?\n";
	}
	bool success = getPrimusSID();
	if (!success) return false;
	return ret;
}
bool NTClient::connect() {
	wsh = new Hub();
	time_t tnow = time(0);
	stringstream uristream;
	uristream  << NT_REALTIME_WS_ENDPOINT << "?_primuscb=" << tnow << "-1&EIO=3&transport=websocket&sid=" << primusSid << "&t=" << tnow << "-2&b64=1";
	string wsURI = uristream.str();
	cout << "Connecting to endpoint: " << wsURI << endl;
	if (firstConnect) {
		addListeners();
	}
	// cout << "Cookies: " << rawCookieStr << endl << endl;
	// Create override headers
	SMap customHeaders;
	cout << rawCookieStr << endl;
	customHeaders["Cookie"] = rawCookieStr;
	customHeaders["Origin"] = "https://www.nitrotype.com";
	customHeaders["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36";
	// customHeaders["Host"] = "realtime1.nitrotype.com";
	wsh->connect(wsURI, (void*)this, customHeaders, 7000);
	// wsh->connect(wsURI);
	if (firstConnect) {
		wsh->run();
		firstConnect = false;
	}
	return true;
}
void NTClient::addCookie(string key, string val) {
	SPair sp = SPair(key, val);
	cookies.push_back(sp);
}
bool NTClient::getPrimusSID() {
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream squery;
	squery << "?_primuscb=" << tnow << "-0&EIO=3&transport=polling&t=" << tnow << "-0&b64=1";
	string queryStr = squery.str();

	httplib::SSLClient loginReq(NT_REALTIME_HOST, HTTPS_PORT);
	string path = NT_PRIMUS_ENDPOINT + queryStr;
	shared_ptr<httplib::Response> res = loginReq.get(path.c_str(), rawCookieStr.c_str());
	if (res) {
		cout << res->body << endl;
		json jres = json::parse(res->body.substr(4, res->body.length()));
		primusSid = jres["sid"];
		cout << "Resolved primus SID: " << primusSid << endl;
		addCookie("io", primusSid);
		rawCookieStr = Utils::stringifyCookies(&cookies);
	} else {
		cout << "Error retrieving primus handshake data.\n";
		return false;
	}
	return true;
}
string NTClient::getJoinPacket(int avgSpeed) {
	json p = {
		{"stream", "race"},
		{"msg", "join"},
		{"payload", {
			{"debugging", false},
			{"avgSpeed", avgSpeed},
			{"track", "desert"},
			{"music", "dirty_bit"},
			{"update", 3417}
		}}
	};
	string ret = "4";
	ret += p.dump();
	return ret;
}
void NTClient::addListeners() {
	assert(wsh != nullptr);
	wsh->onError([this](void* udata) {
		cout << "Failed to connect to WebSocket server." << endl;
		hasError = true;
	});
	wsh->onConnection([this](WebSocket<CLIENT>* wsocket, HttpRequest req) {
		cout << "Connected to the realtime server." << endl;
		cout << req.getUrl().key << endl;
		onConnection(wsocket, req);
	});
	wsh->onDisconnection([this](WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
		cout << "Disconnected from the realtime server." << endl;
		onDisconnection(wsocket, code, msg, len);
	});
	wsh->onMessage([this](WebSocket<SERVER>* ws, char* msg, size_t len, OpCode opCode) {
		onMessage(ws, msg, len, opCode);
	});
}
void NTClient::onDisconnection(WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
	cout << "Disconn message: " << string(msg, len) << endl;
	cout << "Disconn code: " << code << endl;
}
void NTClient::onMessage(WebSocket<SERVER>* ws, char* msg, size_t len, OpCode opCode) {
	cout << "ws message" << endl; // TODO: parse incoming messages
}
void NTClient::onConnection(WebSocket<CLIENT>* wsocket, HttpRequest req) {
	// Send a probe, which is required for connection
	wsocket->send("2probe", OpCode::TEXT);
	/*
	string joinTo = getJoinPacket(100); // 100 WPM just to test
	cout << joinTo << endl;
	wsocket->send(joinTo.c_str());
	*/
}<commit_msg>Move cookie stringification to connect()<commit_after>#include "NTClient.h"
using namespace std;

NTClient::NTClient() {
	hasError = false;
	firstConnect = true;
	connected = false;
}
bool NTClient::login(string username, string password) {
	uname = username;
	pword = password;
	bool ret = true;
	string data = string("username=");
	data += uname;
	data += "&password=";
	data += pword;
	data += "&adb=1&tz=America%2FChicago"; // No need to have anything other than Chicago timezone
	httplib::SSLClient loginReq(NITROTYPE_HOSTNAME, HTTPS_PORT);
	shared_ptr<httplib::Response> res = loginReq.post(NT_LOGIN_ENDPOINT, data, "application/x-www-form-urlencoded; charset=UTF-8");
	if (res) {
		bool foundLoginCookie = false;
		for (int i = 0; i < res->cookies.size(); ++i) {
			string cookie = res->cookies.at(i);
			addCookie(Utils::extractCKey(cookie), Utils::extractCValue(cookie));
			if (cookie.find("ntuserrem=") == 0) {
				foundLoginCookie = true;
				token = Utils::extractCValue(cookie);
				cout << "Retrieved login token: " << token << endl;
				// addCookie("ntuserrem", token);
			}
		}
		if (!foundLoginCookie) {
			ret = false;
			cout << "Unable to locate the login cookie. Maybe try a different account?\n";
		}
	} else {
		ret = false;
		cout << "Login request failed. This might be a network issue. Maybe try resetting your internet connection?\n";
	}
	bool success = getPrimusSID();
	if (!success) return false;
	return ret;
}
bool NTClient::connect() {
	wsh = new Hub();
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream uristream;
	uristream  << NT_REALTIME_WS_ENDPOINT << "?_primuscb=" << tnow << "-1&EIO=3&transport=websocket&sid=" << primusSid << "&t=" << tnow << "-2&b64=1";
	string wsURI = uristream.str();
	cout << "Connecting to endpoint: " << wsURI << endl;
	if (firstConnect) {
		addListeners();
	}
	// cout << "Cookies: " << rawCookieStr << endl << endl;
	// Create override headers
	SMap customHeaders;
	cout << rawCookieStr << endl;
	customHeaders["Cookie"] = rawCookieStr;
	customHeaders["Origin"] = "https://www.nitrotype.com";
	customHeaders["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36";
	// customHeaders["Host"] = "realtime1.nitrotype.com";
	wsh->connect(wsURI, (void*)this, customHeaders, 7000);
	// wsh->connect(wsURI);
	if (firstConnect) {
		wsh->run();
		firstConnect = false;
	}
	return true;
}
void NTClient::addCookie(string key, string val) {
	SPair sp = SPair(key, val);
	cookies.push_back(sp);
}
bool NTClient::getPrimusSID() {
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream squery;
	squery << "?_primuscb=" << tnow << "-0&EIO=3&transport=polling&t=" << tnow << "-0&b64=1";
	string queryStr = squery.str();

	httplib::SSLClient loginReq(NT_REALTIME_HOST, HTTPS_PORT);
	string path = NT_PRIMUS_ENDPOINT + queryStr;
	shared_ptr<httplib::Response> res = loginReq.get(path.c_str(), rawCookieStr.c_str());
	if (res) {
		cout << res->body << endl;
		json jres = json::parse(res->body.substr(4, res->body.length()));
		primusSid = jres["sid"];
		cout << "Resolved primus SID: " << primusSid << endl;
		addCookie("io", primusSid);
	} else {
		cout << "Error retrieving primus handshake data.\n";
		return false;
	}
	return true;
}
string NTClient::getJoinPacket(int avgSpeed) {
	json p = {
		{"stream", "race"},
		{"msg", "join"},
		{"payload", {
			{"debugging", false},
			{"avgSpeed", avgSpeed},
			{"track", "desert"},
			{"music", "dirty_bit"},
			{"update", 3417}
		}}
	};
	string ret = "4";
	ret += p.dump();
	return ret;
}
void NTClient::addListeners() {
	assert(wsh != nullptr);
	wsh->onError([this](void* udata) {
		cout << "Failed to connect to WebSocket server." << endl;
		hasError = true;
	});
	wsh->onConnection([this](WebSocket<CLIENT>* wsocket, HttpRequest req) {
		cout << "Connected to the realtime server." << endl;
		cout << req.getUrl().key << endl;
		onConnection(wsocket, req);
	});
	wsh->onDisconnection([this](WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
		cout << "Disconnected from the realtime server." << endl;
		onDisconnection(wsocket, code, msg, len);
	});
	wsh->onMessage([this](WebSocket<SERVER>* ws, char* msg, size_t len, OpCode opCode) {
		onMessage(ws, msg, len, opCode);
	});
}
void NTClient::onDisconnection(WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
	cout << "Disconn message: " << string(msg, len) << endl;
	cout << "Disconn code: " << code << endl;
}
void NTClient::onMessage(WebSocket<SERVER>* ws, char* msg, size_t len, OpCode opCode) {
	cout << "ws message" << endl; // TODO: parse incoming messages
}
void NTClient::onConnection(WebSocket<CLIENT>* wsocket, HttpRequest req) {
	// Send a probe, which is required for connection
	wsocket->send("2probe", OpCode::TEXT);
	/*
	string joinTo = getJoinPacket(100); // 100 WPM just to test
	cout << joinTo << endl;
	wsocket->send(joinTo.c_str());
	*/
}<|endoftext|>