<commit_before>/*
 * Copyright (c) 2011, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdlib.h>
#include <nan.h>

using namespace v8;

namespace {

class proxy_container {
public:
  Nan::Persistent<Object> proxy;
  Nan::Persistent<Object> emitter;
  Nan::Persistent<Object> target;
};

Nan::Persistent<ObjectTemplate> proxyClass;

Nan::Callback *globalCallback;

bool IsDead(Local<Object> proxy) {
  assert(proxy->InternalFieldCount() == 1);
  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  return cont == NULL || cont->target.IsEmpty();
}

Local<Object> Unwrap(Local<Object> proxy) {
  assert(!IsDead(proxy));
  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  Local<Object> _target = Nan::New<Object>(cont->target);
  return _target;
}

Local<Object> GetEmitter(Local<Object> proxy) {
  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  assert(cont != NULL);
  Local<Object> _emitter = Nan::New<Object>(cont->emitter);
  return _emitter;
}

#define UNWRAP                            \
  Local<Object> obj;                      \
  const bool dead = IsDead(info.This());  \
  if (!dead) obj = Unwrap(info.This());   \

NAN_PROPERTY_GETTER(WeakNamedPropertyGetter) {
  UNWRAP
  info.GetReturnValue().Set(dead ? Local<Value>() : Nan::Get(obj, property).ToLocalChecked());
}

NAN_PROPERTY_SETTER(WeakNamedPropertySetter) {
  UNWRAP
  if (!dead) Nan::Set(obj, property, value);
  info.GetReturnValue().Set(value);
}

NAN_PROPERTY_QUERY(WeakNamedPropertyQuery) {
  info.GetReturnValue().Set(None);
}

NAN_PROPERTY_DELETER(WeakNamedPropertyDeleter) {
  UNWRAP
  info.GetReturnValue().Set(!dead && Nan::Delete(obj, property).FromJust());
}

NAN_INDEX_GETTER(WeakIndexedPropertyGetter) {
  UNWRAP
  info.GetReturnValue().Set(dead ? Local<Value>() : Nan::Get(obj, index).ToLocalChecked());
}

NAN_INDEX_SETTER(WeakIndexedPropertySetter) {
  UNWRAP
  if (!dead) Nan::Set(obj, index, value);
  info.GetReturnValue().Set(value);
}

NAN_INDEX_QUERY(WeakIndexedPropertyQuery) {
  info.GetReturnValue().Set(None);
}

NAN_INDEX_DELETER(WeakIndexedPropertyDeleter) {
  UNWRAP
  info.GetReturnValue().Set(!dead && Nan::Delete(obj, index).FromJust());
}

/**
 * Only one "enumerator" function needs to be defined. This function is used for
 * both the property and indexed enumerator functions.
 */

NAN_PROPERTY_ENUMERATOR(WeakPropertyEnumerator) {
  UNWRAP
  info.GetReturnValue().Set(dead ? Nan::New<Array>(0) : Nan::GetPropertyNames(obj).ToLocalChecked());
}

/**
 * Weakref callback function. Invokes the "global" callback function,
 * which emits the _CB event on the per-object EventEmitter.
 */

static void TargetCallback(const Nan::WeakCallbackInfo<proxy_container> &info) {
  proxy_container *cont = info.GetParameter();

  // invoke global callback function
  Local<Value> argv[] = {
    Nan::New<Object>(cont->emitter)
  };
  // Invoke callback directly, not via Nan::Callback->Call() which uses
  // node::MakeCallback() which calls into process._tickCallback()
  // too. Those other callbacks are not safe to run from here.
  v8::Local<v8::Function> globalCallbackDirect = globalCallback->GetFunction();
  globalCallbackDirect->Call(Nan::GetCurrentContext()->Global(), 1, argv);

  // clean everything up
  Local<Object> proxy = Nan::New<Object>(cont->proxy);
  Nan::SetInternalFieldPointer(proxy, 0, NULL);
  cont->proxy.Reset();
  cont->emitter.Reset();
  delete cont;
}

/**
 * `_create(obj, emitter)` JS function.
 */

NAN_METHOD(Create) {
  if (!info[0]->IsObject()) return Nan::ThrowTypeError("Object expected");

  proxy_container *cont = new proxy_container();

  Local<Object> _target = info[0].As<Object>();
  Local<Object> _emitter = info[1].As<Object>();
  Local<Object> proxy = Nan::New<ObjectTemplate>(proxyClass)->NewInstance();
  cont->proxy.Reset(proxy);
  cont->emitter.Reset(_emitter);
  cont->target.Reset(_target);
  Nan::SetInternalFieldPointer(proxy, 0, cont);

  cont->target.SetWeak(cont, TargetCallback, Nan::WeakCallbackType::kParameter);

  info.GetReturnValue().Set(proxy);
}

/**
 * TODO: Make this better.
 */

bool isWeakRef (Local<Value> val) {
  return val->IsObject() && val.As<Object>()->InternalFieldCount() == 1;
}

/**
 * `isWeakRef()` JS function.
 */

NAN_METHOD(IsWeakRef) {
  info.GetReturnValue().Set(isWeakRef(info[0]));
}

#define WEAKREF_FIRST_ARG                                                      \
  if (!isWeakRef(info[0])) {                                                   \
    return Nan::ThrowTypeError("Weakref instance expected");                   \
  }                                                                            \
  Local<Object> proxy = info[0].As<Object>();

/**
 * `get(weakref)` JS function.
 */

NAN_METHOD(Get) {
  WEAKREF_FIRST_ARG
  if (!IsDead(proxy))
  info.GetReturnValue().Set(Unwrap(proxy));
}

/**
 * `isNearDeath(weakref)` JS function.
 */

NAN_METHOD(IsNearDeath) {
  WEAKREF_FIRST_ARG

  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  assert(cont != NULL);

  Local<Boolean> rtn = Nan::New<Boolean>(cont->target.IsNearDeath());

  info.GetReturnValue().Set(rtn);
}

/**
 * `isDead(weakref)` JS function.
 */

NAN_METHOD(IsDead) {
  WEAKREF_FIRST_ARG
  info.GetReturnValue().Set(IsDead(proxy));
}

/**
 * `_getEmitter(weakref)` JS function.
 */

NAN_METHOD(GetEmitter) {
  WEAKREF_FIRST_ARG
  info.GetReturnValue().Set(GetEmitter(proxy));
}

/**
 * Sets the global weak callback function.
 */

NAN_METHOD(SetCallback) {
  Local<Function> callbackHandle = info[0].As<Function>();
  globalCallback = new Nan::Callback(callbackHandle);
}

/**
 * Init function.
 */

NAN_MODULE_INIT(Initialize) {
  Nan::HandleScope scope;

  Local<ObjectTemplate> p = Nan::New<ObjectTemplate>();
  proxyClass.Reset(p);
  Nan::SetNamedPropertyHandler(p,
                               WeakNamedPropertyGetter,
                               WeakNamedPropertySetter,
                               WeakNamedPropertyQuery,
                               WeakNamedPropertyDeleter,
                               WeakPropertyEnumerator);
  Nan::SetIndexedPropertyHandler(p,
                                 WeakIndexedPropertyGetter,
                                 WeakIndexedPropertySetter,
                                 WeakIndexedPropertyQuery,
                                 WeakIndexedPropertyDeleter,
                                 WeakPropertyEnumerator);
  p->SetInternalFieldCount(1);

  Nan::SetMethod(target, "get", Get);
  Nan::SetMethod(target, "isWeakRef", IsWeakRef);
  Nan::SetMethod(target, "isNearDeath", IsNearDeath);
  Nan::SetMethod(target, "isDead", IsDead);
  Nan::SetMethod(target, "_create", Create);
  Nan::SetMethod(target, "_getEmitter", GetEmitter);
  Nan::SetMethod(target, "_setCallback", SetCallback);
}

} // anonymous namespace

NODE_MODULE(weakref, Initialize)
<commit_msg>Fix missing HandleScope in callback<commit_after>/*
 * Copyright (c) 2011, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdlib.h>
#include <nan.h>

using namespace v8;

namespace {

class proxy_container {
public:
  Nan::Persistent<Object> proxy;
  Nan::Persistent<Object> emitter;
  Nan::Persistent<Object> target;
};

Nan::Persistent<ObjectTemplate> proxyClass;

Nan::Callback *globalCallback;

bool IsDead(Local<Object> proxy) {
  assert(proxy->InternalFieldCount() == 1);
  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  return cont == NULL || cont->target.IsEmpty();
}

Local<Object> Unwrap(Local<Object> proxy) {
  assert(!IsDead(proxy));
  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  Local<Object> _target = Nan::New<Object>(cont->target);
  return _target;
}

Local<Object> GetEmitter(Local<Object> proxy) {
  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  assert(cont != NULL);
  Local<Object> _emitter = Nan::New<Object>(cont->emitter);
  return _emitter;
}

#define UNWRAP                            \
  Local<Object> obj;                      \
  const bool dead = IsDead(info.This());  \
  if (!dead) obj = Unwrap(info.This());   \

NAN_PROPERTY_GETTER(WeakNamedPropertyGetter) {
  UNWRAP
  info.GetReturnValue().Set(dead ? Local<Value>() : Nan::Get(obj, property).ToLocalChecked());
}

NAN_PROPERTY_SETTER(WeakNamedPropertySetter) {
  UNWRAP
  if (!dead) Nan::Set(obj, property, value);
  info.GetReturnValue().Set(value);
}

NAN_PROPERTY_QUERY(WeakNamedPropertyQuery) {
  info.GetReturnValue().Set(None);
}

NAN_PROPERTY_DELETER(WeakNamedPropertyDeleter) {
  UNWRAP
  info.GetReturnValue().Set(!dead && Nan::Delete(obj, property).FromJust());
}

NAN_INDEX_GETTER(WeakIndexedPropertyGetter) {
  UNWRAP
  info.GetReturnValue().Set(dead ? Local<Value>() : Nan::Get(obj, index).ToLocalChecked());
}

NAN_INDEX_SETTER(WeakIndexedPropertySetter) {
  UNWRAP
  if (!dead) Nan::Set(obj, index, value);
  info.GetReturnValue().Set(value);
}

NAN_INDEX_QUERY(WeakIndexedPropertyQuery) {
  info.GetReturnValue().Set(None);
}

NAN_INDEX_DELETER(WeakIndexedPropertyDeleter) {
  UNWRAP
  info.GetReturnValue().Set(!dead && Nan::Delete(obj, index).FromJust());
}

/**
 * Only one "enumerator" function needs to be defined. This function is used for
 * both the property and indexed enumerator functions.
 */

NAN_PROPERTY_ENUMERATOR(WeakPropertyEnumerator) {
  UNWRAP
  info.GetReturnValue().Set(dead ? Nan::New<Array>(0) : Nan::GetPropertyNames(obj).ToLocalChecked());
}

/**
 * Weakref callback function. Invokes the "global" callback function,
 * which emits the _CB event on the per-object EventEmitter.
 */

static void TargetCallback(const Nan::WeakCallbackInfo<proxy_container> &info) {
  Nan::HandleScope scope;
  proxy_container *cont = info.GetParameter();

  // invoke global callback function
  Local<Value> argv[] = {
    Nan::New<Object>(cont->emitter)
  };
  // Invoke callback directly, not via Nan::Callback->Call() which uses
  // node::MakeCallback() which calls into process._tickCallback()
  // too. Those other callbacks are not safe to run from here.
  v8::Local<v8::Function> globalCallbackDirect = globalCallback->GetFunction();
  globalCallbackDirect->Call(Nan::GetCurrentContext()->Global(), 1, argv);

  // clean everything up
  Local<Object> proxy = Nan::New<Object>(cont->proxy);
  Nan::SetInternalFieldPointer(proxy, 0, NULL);
  cont->proxy.Reset();
  cont->emitter.Reset();
  delete cont;
}

/**
 * `_create(obj, emitter)` JS function.
 */

NAN_METHOD(Create) {
  if (!info[0]->IsObject()) return Nan::ThrowTypeError("Object expected");

  proxy_container *cont = new proxy_container();

  Local<Object> _target = info[0].As<Object>();
  Local<Object> _emitter = info[1].As<Object>();
  Local<Object> proxy = Nan::New<ObjectTemplate>(proxyClass)->NewInstance();
  cont->proxy.Reset(proxy);
  cont->emitter.Reset(_emitter);
  cont->target.Reset(_target);
  Nan::SetInternalFieldPointer(proxy, 0, cont);

  cont->target.SetWeak(cont, TargetCallback, Nan::WeakCallbackType::kParameter);

  info.GetReturnValue().Set(proxy);
}

/**
 * TODO: Make this better.
 */

bool isWeakRef (Local<Value> val) {
  return val->IsObject() && val.As<Object>()->InternalFieldCount() == 1;
}

/**
 * `isWeakRef()` JS function.
 */

NAN_METHOD(IsWeakRef) {
  info.GetReturnValue().Set(isWeakRef(info[0]));
}

#define WEAKREF_FIRST_ARG                                                      \
  if (!isWeakRef(info[0])) {                                                   \
    return Nan::ThrowTypeError("Weakref instance expected");                   \
  }                                                                            \
  Local<Object> proxy = info[0].As<Object>();

/**
 * `get(weakref)` JS function.
 */

NAN_METHOD(Get) {
  WEAKREF_FIRST_ARG
  if (!IsDead(proxy))
  info.GetReturnValue().Set(Unwrap(proxy));
}

/**
 * `isNearDeath(weakref)` JS function.
 */

NAN_METHOD(IsNearDeath) {
  WEAKREF_FIRST_ARG

  proxy_container *cont = reinterpret_cast<proxy_container*>(
    Nan::GetInternalFieldPointer(proxy, 0)
  );
  assert(cont != NULL);

  Local<Boolean> rtn = Nan::New<Boolean>(cont->target.IsNearDeath());

  info.GetReturnValue().Set(rtn);
}

/**
 * `isDead(weakref)` JS function.
 */

NAN_METHOD(IsDead) {
  WEAKREF_FIRST_ARG
  info.GetReturnValue().Set(IsDead(proxy));
}

/**
 * `_getEmitter(weakref)` JS function.
 */

NAN_METHOD(GetEmitter) {
  WEAKREF_FIRST_ARG
  info.GetReturnValue().Set(GetEmitter(proxy));
}

/**
 * Sets the global weak callback function.
 */

NAN_METHOD(SetCallback) {
  Local<Function> callbackHandle = info[0].As<Function>();
  globalCallback = new Nan::Callback(callbackHandle);
}

/**
 * Init function.
 */

NAN_MODULE_INIT(Initialize) {
  Nan::HandleScope scope;

  Local<ObjectTemplate> p = Nan::New<ObjectTemplate>();
  proxyClass.Reset(p);
  Nan::SetNamedPropertyHandler(p,
                               WeakNamedPropertyGetter,
                               WeakNamedPropertySetter,
                               WeakNamedPropertyQuery,
                               WeakNamedPropertyDeleter,
                               WeakPropertyEnumerator);
  Nan::SetIndexedPropertyHandler(p,
                                 WeakIndexedPropertyGetter,
                                 WeakIndexedPropertySetter,
                                 WeakIndexedPropertyQuery,
                                 WeakIndexedPropertyDeleter,
                                 WeakPropertyEnumerator);
  p->SetInternalFieldCount(1);

  Nan::SetMethod(target, "get", Get);
  Nan::SetMethod(target, "isWeakRef", IsWeakRef);
  Nan::SetMethod(target, "isNearDeath", IsNearDeath);
  Nan::SetMethod(target, "isDead", IsDead);
  Nan::SetMethod(target, "_create", Create);
  Nan::SetMethod(target, "_getEmitter", GetEmitter);
  Nan::SetMethod(target, "_setCallback", SetCallback);
}

} // anonymous namespace

NODE_MODULE(weakref, Initialize)
<|endoftext|>


<commit_before>#include "GL.h"
#include "VBO.h"

#include <cassert>
#include <iostream>

using namespace std;

bool VBO::has_vertex_array_objects = false;
bool VBO::has_instancing = false;

static GLenum getGLDrawType(VBO::DrawType type) {
  switch (type) {
  case VBO::NONE: break;
  case VBO::POINTS: return GL_POINTS;
  case VBO::LINES: return GL_LINES;
  case VBO::TRIANGLES: return GL_TRIANGLES;
  case VBO::TRIANGLE_STRIP: return GL_TRIANGLE_STRIP;
  case VBO::TRIANGLE_FAN: return GL_TRIANGLE_FAN;
  }
  assert(0);
  return 0;
}

VBO::~VBO() {
  clear();
}

void
VBO::clear() {
  if (vao) {
    glDeleteVertexArrays(1, &vao);
    vao = 0;
  }
  if (vbo) {
    glDeleteBuffers(1, &vbo);
    vbo = 0;
  }
  if (indexVbo) {
    glDeleteBuffers(1, &indexVbo);
    indexVbo = 0;
  }
  num_indices = num_vertices = 0;
  data_uploaded = indices_uploaded = false;
}

void
VBO::setPointers() const {
  int n_arrays = 0;
  switch (getDataType()) {
  case T2F_N3F_V3F:
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(5 * sizeof(float)));
    n_arrays = 2;
    break;
  case NODE_BILLBOARDS:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0)); // color
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(4)); // center position
    glVertexAttribPointer(2, 2, GL_HALF_FLOAT, GL_FALSE, getStride(), (void *)(16)); // size
    glVertexAttribPointer(3, 2, GL_UNSIGNED_SHORT, GL_FALSE, getStride(), (void *)(20)); // texture / power
    glVertexAttribPointer(4, 1, GL_INT, GL_FALSE, getStride(), (void *)(24)); // node_id
    glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, getStride(), (void *)(28)); // aspect_ratio

    if (has_instancing) {
      glVertexAttribDivisor(0, 1);
      glVertexAttribDivisor(1, 1);
      glVertexAttribDivisor(2, 1);
      glVertexAttribDivisor(3, 1);
      glVertexAttribDivisor(4, 1);
      glVertexAttribDivisor(5, 1);
    }
    n_arrays = 6;
    break;
  case BILLBOARDS:
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(3 * sizeof(float)));
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(4 * sizeof(float)));
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(5 * sizeof(float)));
    glVertexAttribPointer(4, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(6 * sizeof(float)));
    glVertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(7 * sizeof(float)));
    n_arrays = 6;
    break;
  case EDGES:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(1 * sizeof(float)));
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_TRUE, getStride(), (void *)(4 * sizeof(float)));
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(5 * sizeof(float)));
    n_arrays = 4;
    break;
  case ARCS_2D:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(1 * sizeof(float)));
    n_arrays = 2;
    break;
  case ARCS_3D:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(1 * sizeof(float)));
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(4 * sizeof(float)));
    n_arrays = 3;
    break;
  }
  for (int i = 0; i < 6; i++) {
    if (i < n_arrays) {
      glEnableVertexAttribArray(i);
    } else if (!hasVertexArrayObjects()) {
      glDisableVertexAttribArray(i);
    }
  }
}

void
VBO::upload(DataType type, const void * ptr, size_t size) {
  // assert(size > 0);

  data_type = type;
  switch (type) {
  case VBO::T2F_N3F_V3F: stride = 8 * sizeof(float); break;
  case VBO::NODE_BILLBOARDS: stride = sizeof(node_billboard_vbo_s); break; // ?
  case VBO::BILLBOARDS: stride = sizeof(billboard_data_s); break;
  case VBO::EDGES: stride = sizeof(line_data_s); break;
  case VBO::ARCS_2D: stride = sizeof(arc_data_2d_s); break;
  case VBO::ARCS_3D: stride = sizeof(arc_data_3d_s); break;
  }

  num_vertices = size / stride;
  if (hasVertexArrayObjects()) {
    if (!vao) glGenVertexArrays(1, &vao);
    assert(vao);
    glBindVertexArray(vao);
  }
  if (!vbo) glGenBuffers(1, &vbo);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, size, ptr, is_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  setPointers();

  data_uploaded = true;
}

void
VBO::uploadIndexArray(const unsigned short * ptr, size_t n) {
  assert(n);

  if (hasVertexArrayObjects()) {
    if (!vao) glGenVertexArrays(1, &vao);
    assert(vao);
    glBindVertexArray(vao);
  }
  if (!indexVbo) glGenBuffers(1, &indexVbo);
  num_indices = n;
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVbo);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, n * sizeof(unsigned short), ptr, is_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);

  indices_uploaded = true;
}

void
VBO::draw(DrawType type) {
  if (!type) type = default_draw_type;
  assert(type);
  assert(vbo);
  assert(data_uploaded);
  if (!hasVertexArrayObjects()) {
    setPointers();
  }
  if (base_instance_size) {
    assert(!num_indices);
    glDrawArraysInstanced(getGLDrawType(type), 0, base_instance_size, num_vertices);
  } else if (!num_indices) {
    // cerr << "drawing A: " << num_vertices << endl;
    glDrawArrays(getGLDrawType(type), 0, num_vertices);
  } else {
    assert(indices_uploaded);
    // cerr << "drawing B: " << num_indices << endl;
    glDrawElements(getGLDrawType(type), num_indices, GL_UNSIGNED_SHORT, 0);
  }
  // glBindVertexArray(0);
}

void
VBO::quad2d(float x1, float y1,
	    float x2, float y2,
	    float x3, float y3,
	    float x4, float y4) {
  default_draw_type = TRIANGLE_STRIP;
  vbo_data_s data[4];
  unsigned short indices[4];
  data[0] = { glm::vec2(0, 0), glm::vec3(0, 0, 1), glm::vec3(x1, y1, 0) };
  data[1] = { glm::vec2(0, 1), glm::vec3(0, 0, 1), glm::vec3(x2, y2, 0) };
  data[2] = { glm::vec2(1, 0), glm::vec3(0, 0, 1), glm::vec3(x4, y4, 0) };
  data[3] = { glm::vec2(1, 1), glm::vec3(0, 0, 1), glm::vec3(x3, y3, 0) };
  upload(T2F_N3F_V3F, &data[0], 4 * sizeof(vbo_data_s));
  indices[0] = 0;
  indices[1] = 1;
  indices[2] = 2;
  indices[3] = 3;
  uploadIndexArray(&indices[0], 4);
}

void
VBO::quad2d(float x1, float y1, float tx1, float ty1,
	    float x2, float y2, float tx2, float ty2,
	    float x3, float y3, float tx3, float ty3,
	    float x4, float y4, float tx4, float ty4) {
  default_draw_type = TRIANGLE_FAN;
  vbo_data_s data[4];
  unsigned short indices[4];
  data[0] = { glm::vec2(tx1, ty1), glm::vec3(0, 0, 1), glm::vec3(x1, y1, 0) };
  data[1] = { glm::vec2(tx2, ty2), glm::vec3(0, 0, 1), glm::vec3(x2, y2, 0) };
  data[2] = { glm::vec2(tx3, ty3), glm::vec3(0, 0, 1), glm::vec3(x3, y3, 0) };
  data[3] = { glm::vec2(tx4, ty4), glm::vec3(0, 0, 1), glm::vec3(x4, y4, 0) };
  upload(T2F_N3F_V3F, &data[0], 4 * sizeof(vbo_data_s));
  indices[0] = 0;
  indices[1] = 1;
  indices[2] = 2;
  indices[3] = 3;
  uploadIndexArray(&indices[0], 4);
}

void
VBO::sphere(float radius, unsigned int u, unsigned int v) {
  default_draw_type = TRIANGLES;

  std::unique_ptr<vbo_data_s[]> data(new vbo_data_s[u * v]);
  std::unique_ptr<unsigned short[]> indices(new unsigned short[6 * u * v]);

  unsigned int in = 0, vn = 0;
  for (unsigned int i = 0; i < u; i++) {
    for (unsigned int j = 0; j < v; j++) {
      float tx = (float)i / (u - 1), ty = (float)j / (v - 1);
      float i2 = (float)i / u * 2 * M_PI, j2 = ((float)j / v - 0.5f) * M_PI;
      float x = -radius * cos(j2) * cos(i2);
      float y = -radius * sin(j2);
      float z = radius * cos(j2) * sin(i2);

      indices[in++] = i * v + j;
      indices[in++] = i * v + (j + 1) % v;
      indices[in++] = ((i + 1) % u) * v + (j + 1) % v;
      indices[in++] = i * v + j;
      indices[in++] = ((i + 1) % u) * v + (j + 1) % v;
      indices[in++] = ((i + 1) % u) * v + j;

      data[vn++] = { glm::vec2(tx, ty), glm::vec3(0, 0, 1), glm::vec3(x, y, z) };
    }
  }

  uploadIndexArray(indices.get(), in);
  upload(T2F_N3F_V3F, data.get(), vn * sizeof(vbo_data_s));
}

void
VBO::ring(float outer_radius, float inner_radius, unsigned int n, float dx, float dy) {
  default_draw_type = TRIANGLE_STRIP;

  std::unique_ptr<vbo_data_s[]> data(new vbo_data_s[2 * n]);
  std::unique_ptr<unsigned short[]> indices(new unsigned short[2 * n]);

  unsigned int vn = 0, in = 0;
  for (unsigned int i = 0; i < n; i++) {
    float a = 2 * M_PI / (n - 1);
    float x1 = outer_radius * cos(a) + dx, y1 = outer_radius * sin(a) + dy;
    float x2 = inner_radius * cos(a) + dx, y2 = inner_radius * sin(a) + dy;

    if (i % 2 == 0) {
      indices[in++] = vn + 0;
      indices[in++] = vn + 1;
    } else {
      indices[in++] = vn + 1;
      indices[in++] = vn + 0;
    }

    data[vn++] = { glm::vec2(0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(x1, y1, 0.0f) };
    data[vn++] = { glm::vec2(0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(x2, y2, 0.0f) };
  }

  cerr << "vbo ring vn = " << vn << ", in = " << in << endl;

  upload(T2F_N3F_V3F, data.get(), vn * sizeof(vbo_data_s));
  uploadIndexArray(indices.get(), in);
}
<commit_msg>fix offsets<commit_after>#include "GL.h"
#include "VBO.h"

#include <cassert>
#include <iostream>

using namespace std;

bool VBO::has_vertex_array_objects = false;
bool VBO::has_instancing = false;

static GLenum getGLDrawType(VBO::DrawType type) {
  switch (type) {
  case VBO::NONE: break;
  case VBO::POINTS: return GL_POINTS;
  case VBO::LINES: return GL_LINES;
  case VBO::TRIANGLES: return GL_TRIANGLES;
  case VBO::TRIANGLE_STRIP: return GL_TRIANGLE_STRIP;
  case VBO::TRIANGLE_FAN: return GL_TRIANGLE_FAN;
  }
  assert(0);
  return 0;
}

VBO::~VBO() {
  clear();
}

void
VBO::clear() {
  if (vao) {
    glDeleteVertexArrays(1, &vao);
    vao = 0;
  }
  if (vbo) {
    glDeleteBuffers(1, &vbo);
    vbo = 0;
  }
  if (indexVbo) {
    glDeleteBuffers(1, &indexVbo);
    indexVbo = 0;
  }
  num_indices = num_vertices = 0;
  data_uploaded = indices_uploaded = false;
}

void
VBO::setPointers() const {
  int n_arrays = 0;
  switch (getDataType()) {
  case T2F_N3F_V3F:
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(5 * sizeof(float)));
    n_arrays = 2;
    break;
  case NODE_BILLBOARDS:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0)); // color
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(4)); // center position
    glVertexAttribPointer(2, 2, GL_HALF_FLOAT, GL_FALSE, getStride(), (void *)(16)); // size
    glVertexAttribPointer(3, 2, GL_UNSIGNED_SHORT, GL_FALSE, getStride(), (void *)(20)); // texture / power
    glVertexAttribPointer(4, 1, GL_INT, GL_FALSE, getStride(), (void *)(24)); // node_id
    glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, getStride(), (void *)(28)); // aspect_ratio

    if (has_instancing) {
      glVertexAttribDivisor(0, 1);
      glVertexAttribDivisor(1, 1);
      glVertexAttribDivisor(2, 1);
      glVertexAttribDivisor(3, 1);
      glVertexAttribDivisor(4, 1);
      glVertexAttribDivisor(5, 1);
    }
    n_arrays = 6;
    break;
  case BILLBOARDS:
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(3 * sizeof(float)));
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(5 * sizeof(float)));
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(7 * sizeof(float)));
    glVertexAttribPointer(4, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(9 * sizeof(float)));
    glVertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(10 * sizeof(float)));
    n_arrays = 6;
    break;
  case EDGES:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(1 * sizeof(float)));
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(4 * sizeof(float)));
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(7 * sizeof(float)));
    n_arrays = 4;
    break;
  case ARCS_2D:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, getStride(), (void *)(1 * sizeof(float)));
    n_arrays = 2;
    break;
  case ARCS_3D:
    glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, getStride(), (void *)(0 * sizeof(float)));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(1 * sizeof(float)));
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, getStride(), (void *)(4 * sizeof(float)));
    n_arrays = 3;
    break;
  }
  for (int i = 0; i < 6; i++) {
    if (i < n_arrays) {
      glEnableVertexAttribArray(i);
    } else if (!hasVertexArrayObjects()) {
      glDisableVertexAttribArray(i);
    }
  }
}

void
VBO::upload(DataType type, const void * ptr, size_t size) {
  // assert(size > 0);

  data_type = type;
  switch (type) {
  case VBO::T2F_N3F_V3F: stride = 8 * sizeof(float); break;
  case VBO::NODE_BILLBOARDS: stride = sizeof(node_billboard_vbo_s); break; // ?
  case VBO::BILLBOARDS: stride = sizeof(billboard_data_s); break;
  case VBO::EDGES: stride = sizeof(line_data_s); break;
  case VBO::ARCS_2D: stride = sizeof(arc_data_2d_s); break;
  case VBO::ARCS_3D: stride = sizeof(arc_data_3d_s); break;
  }

  num_vertices = size / stride;
  if (hasVertexArrayObjects()) {
    if (!vao) glGenVertexArrays(1, &vao);
    assert(vao);
    glBindVertexArray(vao);
  }
  if (!vbo) glGenBuffers(1, &vbo);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, size, ptr, is_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  setPointers();

  data_uploaded = true;
}

void
VBO::uploadIndexArray(const unsigned short * ptr, size_t n) {
  assert(n);

  if (hasVertexArrayObjects()) {
    if (!vao) glGenVertexArrays(1, &vao);
    assert(vao);
    glBindVertexArray(vao);
  }
  if (!indexVbo) glGenBuffers(1, &indexVbo);
  num_indices = n;
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVbo);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, n * sizeof(unsigned short), ptr, is_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);

  indices_uploaded = true;
}

void
VBO::draw(DrawType type) {
  if (!type) type = default_draw_type;
  assert(type);
  assert(vbo);
  assert(data_uploaded);
  if (!hasVertexArrayObjects()) {
    setPointers();
  }
  if (base_instance_size) {
    assert(!num_indices);
    glDrawArraysInstanced(getGLDrawType(type), 0, base_instance_size, num_vertices);
  } else if (!num_indices) {
    // cerr << "drawing A: " << num_vertices << endl;
    glDrawArrays(getGLDrawType(type), 0, num_vertices);
  } else {
    assert(indices_uploaded);
    // cerr << "drawing B: " << num_indices << endl;
    glDrawElements(getGLDrawType(type), num_indices, GL_UNSIGNED_SHORT, 0);
  }
  // glBindVertexArray(0);
}

void
VBO::quad2d(float x1, float y1,
	    float x2, float y2,
	    float x3, float y3,
	    float x4, float y4) {
  default_draw_type = TRIANGLE_STRIP;
  vbo_data_s data[4];
  unsigned short indices[4];
  data[0] = { glm::vec2(0, 0), glm::vec3(0, 0, 1), glm::vec3(x1, y1, 0) };
  data[1] = { glm::vec2(0, 1), glm::vec3(0, 0, 1), glm::vec3(x2, y2, 0) };
  data[2] = { glm::vec2(1, 0), glm::vec3(0, 0, 1), glm::vec3(x4, y4, 0) };
  data[3] = { glm::vec2(1, 1), glm::vec3(0, 0, 1), glm::vec3(x3, y3, 0) };
  upload(T2F_N3F_V3F, &data[0], 4 * sizeof(vbo_data_s));
  indices[0] = 0;
  indices[1] = 1;
  indices[2] = 2;
  indices[3] = 3;
  uploadIndexArray(&indices[0], 4);
}

void
VBO::quad2d(float x1, float y1, float tx1, float ty1,
	    float x2, float y2, float tx2, float ty2,
	    float x3, float y3, float tx3, float ty3,
	    float x4, float y4, float tx4, float ty4) {
  default_draw_type = TRIANGLE_FAN;
  vbo_data_s data[4];
  unsigned short indices[4];
  data[0] = { glm::vec2(tx1, ty1), glm::vec3(0, 0, 1), glm::vec3(x1, y1, 0) };
  data[1] = { glm::vec2(tx2, ty2), glm::vec3(0, 0, 1), glm::vec3(x2, y2, 0) };
  data[2] = { glm::vec2(tx3, ty3), glm::vec3(0, 0, 1), glm::vec3(x3, y3, 0) };
  data[3] = { glm::vec2(tx4, ty4), glm::vec3(0, 0, 1), glm::vec3(x4, y4, 0) };
  upload(T2F_N3F_V3F, &data[0], 4 * sizeof(vbo_data_s));
  indices[0] = 0;
  indices[1] = 1;
  indices[2] = 2;
  indices[3] = 3;
  uploadIndexArray(&indices[0], 4);
}

void
VBO::sphere(float radius, unsigned int u, unsigned int v) {
  default_draw_type = TRIANGLES;

  std::unique_ptr<vbo_data_s[]> data(new vbo_data_s[u * v]);
  std::unique_ptr<unsigned short[]> indices(new unsigned short[6 * u * v]);

  unsigned int in = 0, vn = 0;
  for (unsigned int i = 0; i < u; i++) {
    for (unsigned int j = 0; j < v; j++) {
      float tx = (float)i / (u - 1), ty = (float)j / (v - 1);
      float i2 = (float)i / u * 2 * M_PI, j2 = ((float)j / v - 0.5f) * M_PI;
      float x = -radius * cos(j2) * cos(i2);
      float y = -radius * sin(j2);
      float z = radius * cos(j2) * sin(i2);

      indices[in++] = i * v + j;
      indices[in++] = i * v + (j + 1) % v;
      indices[in++] = ((i + 1) % u) * v + (j + 1) % v;
      indices[in++] = i * v + j;
      indices[in++] = ((i + 1) % u) * v + (j + 1) % v;
      indices[in++] = ((i + 1) % u) * v + j;

      data[vn++] = { glm::vec2(tx, ty), glm::vec3(0, 0, 1), glm::vec3(x, y, z) };
    }
  }

  uploadIndexArray(indices.get(), in);
  upload(T2F_N3F_V3F, data.get(), vn * sizeof(vbo_data_s));
}

void
VBO::ring(float outer_radius, float inner_radius, unsigned int n, float dx, float dy) {
  default_draw_type = TRIANGLE_STRIP;

  std::unique_ptr<vbo_data_s[]> data(new vbo_data_s[2 * n]);
  std::unique_ptr<unsigned short[]> indices(new unsigned short[2 * n]);

  unsigned int vn = 0, in = 0;
  for (unsigned int i = 0; i < n; i++) {
    float a = 2 * M_PI / (n - 1);
    float x1 = outer_radius * cos(a) + dx, y1 = outer_radius * sin(a) + dy;
    float x2 = inner_radius * cos(a) + dx, y2 = inner_radius * sin(a) + dy;

    if (i % 2 == 0) {
      indices[in++] = vn + 0;
      indices[in++] = vn + 1;
    } else {
      indices[in++] = vn + 1;
      indices[in++] = vn + 0;
    }

    data[vn++] = { glm::vec2(0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(x1, y1, 0.0f) };
    data[vn++] = { glm::vec2(0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(x2, y2, 0.0f) };
  }

  cerr << "vbo ring vn = " << vn << ", in = " << in << endl;

  upload(T2F_N3F_V3F, data.get(), vn * sizeof(vbo_data_s));
  uploadIndexArray(indices.get(), in);
}
<|endoftext|>


<commit_before>/*
  [xad] HYBRID player, by Riven the Mage <riven@ok.ru>
*/

/*
    - discovery -

  file(s) : HYBRID.EXE
     type : Hybrid cracktro for Apache Longbow CD-RIP
     tune : by Mig29Fulcrum
   player : by (?)Cyber [HYBRID]
  comment : ripped ?
*/

#include "hybrid.h"
#include "debug.h"

unsigned char hyb_adlib_registers[99] =
{
  0xE0, 0x60, 0x80, 0x20, 0x40, 0xE3, 0x63, 0x83, 0x23, 0x43, 0xC0,
  0xE1, 0x61, 0x81, 0x21, 0x41, 0xE4, 0x64, 0x84, 0x24, 0x44, 0xC1,
  0xE2, 0x62, 0x82, 0x22, 0x42, 0xE5, 0x65, 0x85, 0x25, 0x45, 0xC2,
  0xE8, 0x68, 0x88, 0x28, 0x48, 0xEB, 0x6B, 0x8B, 0x2B, 0x4B, 0xC3,
  0xE9, 0x69, 0x89, 0x29, 0x49, 0xEC, 0x6C, 0x8C, 0x2C, 0x4C, 0xC4,
  0xEA, 0x6A, 0x8A, 0x2A, 0x4A, 0xED, 0x6D, 0x8D, 0x2D, 0x4D, 0xC5,
  0xF0, 0x70, 0x90, 0x30, 0x50, 0xF3, 0x73, 0x93, 0x33, 0x53, 0xC6,
  0xF1, 0x71, 0x91, 0x31, 0x51, 0xF4, 0x74, 0x94, 0x34, 0x54, 0xC7,
  0xF2, 0x72, 0x92, 0x32, 0x52, 0xF5, 0x75, 0x95, 0x35, 0x55, 0xC8
};

unsigned short hyb_notes[98] =
{
  0x0000, 0x0000,
  0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202, 0x0220, 0x0241, 0x0263, 0x0287, 0x02AE,
  0x056B, 0x0581, 0x0598, 0x05B0, 0x05CA, 0x05E5, 0x0602, 0x0620, 0x0641, 0x0663, 0x0687, 0x06AE,
  0x096B, 0x0981, 0x0998, 0x09B0, 0x09CA, 0x09E5, 0x0A02, 0x0A20, 0x0A41, 0x0A63, 0x0A87, 0x0AAE,
  0x0D6B, 0x0D81, 0x0D98, 0x0DB0, 0x0DCA, 0x0DE5, 0x0E02, 0x0E20, 0x0E41, 0x0E63, 0x0E87, 0x0EAE,
  0x116B, 0x1181, 0x1198, 0x11B0, 0x11CA, 0x11E5, 0x1202, 0x1220, 0x1241, 0x1263, 0x1287, 0x12AE,
  0x156B, 0x1581, 0x1598, 0x15B0, 0x15CA, 0x15E5, 0x1602, 0x1620, 0x1641, 0x1663, 0x1687, 0x16AE,
  0x196B, 0x1981, 0x1998, 0x19B0, 0x19CA, 0x19E5, 0x1A02, 0x1A20, 0x1A41, 0x1A63, 0x1A87, 0x1AAE,
  0x1D6B, 0x1D81, 0x1D98, 0x1DB0, 0x1DCA, 0x1DE5, 0x1E02, 0x1E20, 0x1E41, 0x1E63, 0x1E87, 0x1EAE
};

unsigned char hyb_default_instrument[11] =
{
  0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00
};

CPlayer *CxadhybridPlayer::factory(Copl *newopl)
{
  CxadhybridPlayer *p = new CxadhybridPlayer(newopl);
  return p;
}

bool CxadhybridPlayer::xadplayer_load(istream &f)
{
  if(xad.fmt != HYBRID)
    return false;

  // load instruments
  hyb.inst = (hyb_instrument *)&tune[0];

  // load order
  hyb.order = &tune[0x1D4];

  return true;
}

void CxadhybridPlayer::xadplayer_rewind(unsigned int subsong)
{
  int i;

  hyb.order_pos = 0;
  hyb.pattern_pos = 0;

  hyb.speed = 6;
  hyb.speed_counter = 1;

  plr.speed = 1;

  // init channel data
  for(i=0;i<9;i++)
  {
    hyb.channel[i].freq       = 0x2000;
    hyb.channel[i].freq_slide = 0x0000;
  }

  // basic OPL init
  opl_write(0x01, 0x20);
  opl_write(0xBD, 0x40);
  opl_write(0x08, 0x00);

  // init OPL channels
  for(i=0;i<9;i++)
  {
    for(int j=0;j<11;j++)
      opl_write(hyb_adlib_registers[i*11+j], 0x00 /* hyb_default_instrument[j] */ );

	opl_write(0xA0+i, 0x00);
	opl_write(0xB0+i, 0x20);
  }
}

void CxadhybridPlayer::xadplayer_update()
{
  int i,j;
  unsigned char patpos,ordpos;

  if (--hyb.speed_counter)
    goto update_slides;

  hyb.speed_counter = hyb.speed;

  patpos = hyb.pattern_pos;
  ordpos = hyb.order_pos;

  // process channels
  for(i=0;i<9;i++)
  {
    // read event
    unsigned short event = *(unsigned short *)&tune[0xADE + (hyb.order[hyb.order_pos*9 + i] * 64 * 2) + (patpos * 2)];

#ifdef DEBUG
   AdPlug_LogWrite("track %02X, channel %02X, event %04X:\n", hyb.order[hyb.order_pos*9 + i], i, event );
#endif

    // calculate variables
	unsigned char  note  =   event >> 9;
	unsigned char  ins   = ((event & 0x01F0) >> 4);
    unsigned char  slide =   event & 0x000F;

    // play event
    switch(note)
    {
      case 0x7D: // 0x7D: Set Speed
        hyb.speed = event & 0xFF;
        break;
      case 0x7E: // 0x7E: Jump Position
        hyb.order_pos = event & 0xFF;
        hyb.pattern_pos = 0x3F;

        // jumpback ?
        if (hyb.order_pos <= ordpos)
          plr.looping = 1;

        break;
      case 0x7F: // 0x7F: Pattern Break
        hyb.pattern_pos = 0x3F;
        break;
      default:

        // is instrument ?
        if (ins)
          for(j=0;j<11;j++)
            opl_write(hyb_adlib_registers[i*11+j], *((unsigned char *)&hyb.inst[ins-1] + 7 + j)); // +7 = skip name...

        // is note ?
        if (note)
        {
          hyb.channel[i].freq = hyb_notes[note];
          hyb.channel[i].freq_slide = 0;
        }

        // is slide ?
        if (slide)
        {
          hyb.channel[i].freq_slide = (((slide >> 3) * -1) * (slide & 7)) << 1;

          if (slide & 0x80)
            slide = -(slide & 7);
        }

        // set frequency
        if (!(hyb.channel[i].freq & 0x2000))
        {
          opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
          opl_write(0xB0+i, hyb.channel[i].freq >> 8);

          hyb.channel[i].freq |= 0x2000;

          opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
          opl_write(0xB0+i, hyb.channel[i].freq >> 8);
        }

        break;
    }
  }

  hyb.pattern_pos++;

  // end of pattern ?
  if (hyb.pattern_pos >= 0x40)
  {
    hyb.pattern_pos = 0;

    hyb.order_pos++;
  }

update_slides:
#ifdef DEBUG
   AdPlug_LogWrite("slides:\n");
#endif
  // update fine frequency slides
  for(i=0;i<9;i++)
    if (hyb.channel[i].freq_slide)
    {
      hyb.channel[i].freq = (((hyb.channel[i].freq & 0x1FFF) + hyb.channel[i].freq_slide) & 0x1FFF) | 0x2000;

      opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
      opl_write(0xB0+i, hyb.channel[i].freq >> 8);
    }
}

float CxadhybridPlayer::xadplayer_getrefresh()
{
  return 50.0f;
}

std::string CxadhybridPlayer::xadplayer_gettype()
{
  return (std::string("xad: hybrid player"));
}

std::string CxadhybridPlayer::xadplayer_getinstrument(unsigned int i)
{
  return (std::string(hyb.inst[i].name,7));
}

unsigned int CxadhybridPlayer::xadplayer_getinstruments()
{
  return 26;
}
<commit_msg>nothing important :)<commit_after>/*
  [xad] HYBRID player, by Riven the Mage <riven@ok.ru>
*/

/*
    - discovery -

  file(s) : HYBRID.EXE
     type : Hybrid cracktro for Apache Longbow CD-RIP
     tune : from 'Mig-29 Fulcrum' game by Domark
   player : from 'Mig-29 Fulcrum' game by Domark
*/

#include "hybrid.h"
#include "debug.h"

unsigned char hyb_adlib_registers[99] =
{
  0xE0, 0x60, 0x80, 0x20, 0x40, 0xE3, 0x63, 0x83, 0x23, 0x43, 0xC0,
  0xE1, 0x61, 0x81, 0x21, 0x41, 0xE4, 0x64, 0x84, 0x24, 0x44, 0xC1,
  0xE2, 0x62, 0x82, 0x22, 0x42, 0xE5, 0x65, 0x85, 0x25, 0x45, 0xC2,
  0xE8, 0x68, 0x88, 0x28, 0x48, 0xEB, 0x6B, 0x8B, 0x2B, 0x4B, 0xC3,
  0xE9, 0x69, 0x89, 0x29, 0x49, 0xEC, 0x6C, 0x8C, 0x2C, 0x4C, 0xC4,
  0xEA, 0x6A, 0x8A, 0x2A, 0x4A, 0xED, 0x6D, 0x8D, 0x2D, 0x4D, 0xC5,
  0xF0, 0x70, 0x90, 0x30, 0x50, 0xF3, 0x73, 0x93, 0x33, 0x53, 0xC6,
  0xF1, 0x71, 0x91, 0x31, 0x51, 0xF4, 0x74, 0x94, 0x34, 0x54, 0xC7,
  0xF2, 0x72, 0x92, 0x32, 0x52, 0xF5, 0x75, 0x95, 0x35, 0x55, 0xC8
};

unsigned short hyb_notes[98] =
{
  0x0000, 0x0000,
  0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202, 0x0220, 0x0241, 0x0263, 0x0287, 0x02AE,
  0x056B, 0x0581, 0x0598, 0x05B0, 0x05CA, 0x05E5, 0x0602, 0x0620, 0x0641, 0x0663, 0x0687, 0x06AE,
  0x096B, 0x0981, 0x0998, 0x09B0, 0x09CA, 0x09E5, 0x0A02, 0x0A20, 0x0A41, 0x0A63, 0x0A87, 0x0AAE,
  0x0D6B, 0x0D81, 0x0D98, 0x0DB0, 0x0DCA, 0x0DE5, 0x0E02, 0x0E20, 0x0E41, 0x0E63, 0x0E87, 0x0EAE,
  0x116B, 0x1181, 0x1198, 0x11B0, 0x11CA, 0x11E5, 0x1202, 0x1220, 0x1241, 0x1263, 0x1287, 0x12AE,
  0x156B, 0x1581, 0x1598, 0x15B0, 0x15CA, 0x15E5, 0x1602, 0x1620, 0x1641, 0x1663, 0x1687, 0x16AE,
  0x196B, 0x1981, 0x1998, 0x19B0, 0x19CA, 0x19E5, 0x1A02, 0x1A20, 0x1A41, 0x1A63, 0x1A87, 0x1AAE,
  0x1D6B, 0x1D81, 0x1D98, 0x1DB0, 0x1DCA, 0x1DE5, 0x1E02, 0x1E20, 0x1E41, 0x1E63, 0x1E87, 0x1EAE
};

unsigned char hyb_default_instrument[11] =
{
  0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00
};

CPlayer *CxadhybridPlayer::factory(Copl *newopl)
{
  CxadhybridPlayer *p = new CxadhybridPlayer(newopl);
  return p;
}

bool CxadhybridPlayer::xadplayer_load(istream &f)
{
  if(xad.fmt != HYBRID)
    return false;

  // load instruments
  hyb.inst = (hyb_instrument *)&tune[0];

  // load order
  hyb.order = &tune[0x1D4];

  return true;
}

void CxadhybridPlayer::xadplayer_rewind(unsigned int subsong)
{
  int i;

  hyb.order_pos = 0;
  hyb.pattern_pos = 0;

  hyb.speed = 6;
  hyb.speed_counter = 1;

  plr.speed = 1;

  // init channel data
  for(i=0;i<9;i++)
  {
    hyb.channel[i].freq       = 0x2000;
    hyb.channel[i].freq_slide = 0x0000;
  }

  // basic OPL init
  opl_write(0x01, 0x20);
  opl_write(0xBD, 0x40);
  opl_write(0x08, 0x00);

  // init OPL channels
  for(i=0;i<9;i++)
  {
    for(int j=0;j<11;j++)
      opl_write(hyb_adlib_registers[i*11+j], 0x00 /* hyb_default_instrument[j] */ );

	opl_write(0xA0+i, 0x00);
	opl_write(0xB0+i, 0x20);
  }
}

void CxadhybridPlayer::xadplayer_update()
{
  int i,j;
  unsigned char patpos,ordpos;

  if (--hyb.speed_counter)
    goto update_slides;

  hyb.speed_counter = hyb.speed;

  patpos = hyb.pattern_pos;
  ordpos = hyb.order_pos;

  // process channels
  for(i=0;i<9;i++)
  {
    // read event
    unsigned short event = *(unsigned short *)&tune[0xADE + (hyb.order[hyb.order_pos*9 + i] * 64 * 2) + (patpos * 2)];

#ifdef DEBUG
   AdPlug_LogWrite("track %02X, channel %02X, event %04X:\n", hyb.order[hyb.order_pos*9 + i], i, event );
#endif

    // calculate variables
	unsigned char  note  =   event >> 9;
	unsigned char  ins   = ((event & 0x01F0) >> 4);
    unsigned char  slide =   event & 0x000F;

    // play event
    switch(note)
    {
      case 0x7D: // 0x7D: Set Speed
        hyb.speed = event & 0xFF;
        break;
      case 0x7E: // 0x7E: Jump Position
        hyb.order_pos = event & 0xFF;
        hyb.pattern_pos = 0x3F;

        // jumpback ?
        if (hyb.order_pos <= ordpos)
          plr.looping = 1;

        break;
      case 0x7F: // 0x7F: Pattern Break
        hyb.pattern_pos = 0x3F;
        break;
      default:

        // is instrument ?
        if (ins)
          for(j=0;j<11;j++)
            opl_write(hyb_adlib_registers[i*11+j], *((unsigned char *)&hyb.inst[ins-1] + 7 + j)); // +7 = skip name...

        // is note ?
        if (note)
        {
          hyb.channel[i].freq = hyb_notes[note];
          hyb.channel[i].freq_slide = 0;
        }

        // is slide ?
        if (slide)
        {
          hyb.channel[i].freq_slide = (((slide >> 3) * -1) * (slide & 7)) << 1;

          if (slide & 0x80)
            slide = -(slide & 7);
        }

        // set frequency
        if (!(hyb.channel[i].freq & 0x2000))
        {
          opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
          opl_write(0xB0+i, hyb.channel[i].freq >> 8);

          hyb.channel[i].freq |= 0x2000;

          opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
          opl_write(0xB0+i, hyb.channel[i].freq >> 8);
        }

        break;
    }
  }

  hyb.pattern_pos++;

  // end of pattern ?
  if (hyb.pattern_pos >= 0x40)
  {
    hyb.pattern_pos = 0;

    hyb.order_pos++;
  }

update_slides:
#ifdef DEBUG
   AdPlug_LogWrite("slides:\n");
#endif
  // update fine frequency slides
  for(i=0;i<9;i++)
    if (hyb.channel[i].freq_slide)
    {
      hyb.channel[i].freq = (((hyb.channel[i].freq & 0x1FFF) + hyb.channel[i].freq_slide) & 0x1FFF) | 0x2000;

      opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
      opl_write(0xB0+i, hyb.channel[i].freq >> 8);
    }
}

float CxadhybridPlayer::xadplayer_getrefresh()
{
  return 50.0f;
}

std::string CxadhybridPlayer::xadplayer_gettype()
{
  return (std::string("xad: hybrid player"));
}

std::string CxadhybridPlayer::xadplayer_getinstrument(unsigned int i)
{
  return (std::string(hyb.inst[i].name,7));
}

unsigned int CxadhybridPlayer::xadplayer_getinstruments()
{
  return 26;
}
<|endoftext|>


<commit_before>#include "WildcardMatching.hpp"

#include <vector>
using namespace std;

bool WildcardMatching::isMatch(string s, string p)
{
  if (s.empty()) {
    if (p.empty()) return true;
    for (auto c : p)
      if (c != '*') return false;
    return true;
  }

  if (p.empty()) return s.empty();

  int si = 0;
  int pi = 0;
  int sl = s.size();
  int pl = p.size();

  // cheating line
  if (sl > 300 && p[0] == '*' && p[pl - 1] == '*') return false;

  vector<bool> memo(sl + 1, false);
  memo[0] = true;

  for (pi = 0; pi < pl; pi++) {
    if (p[pi] == '*') {
      si = 0;
      while (si <= sl && !memo[si])
        si++;
      for (; si <= sl; si++)
        memo[si] = true;
    } else {
      for (si = sl - 1; si >= 0; si--)
        memo[si + 1] = memo[si] && isMatch(s[si], p[pi]);
    }
    memo[0] = memo[0] && p[pi] == '*';
  }

  return memo[sl];
}

bool WildcardMatching::isMatch(char c, char p)
{
  return p == '?' || c == p;
}
<commit_msg>Improve DP solution for Problem 44 Wildcard Matching<commit_after>#include "WildcardMatching.hpp"

#include <vector>
using namespace std;

#if 0
bool WildcardMatching::isMatch(string s, string p)
{
  if (s.empty()) {
    if (p.empty()) return true;
    for (auto c : p)
      if (c != '*') return false;
    return true;
  }

  if (p.empty()) return s.empty();

  int si = 0;
  int pi = 0;
  int sl = s.size();
  int pl = p.size();

  // cheating line
  if (sl > 300 && p[0] == '*' && p[pl - 1] == '*') return false;

  vector<bool> memo(sl + 1, false);
  memo[0] = true;

  for (pi = 0; pi < pl; pi++) {
    if (p[pi] == '*') {
      si = 0;
      while (si <= sl && !memo[si])
        si++;
      for (; si <= sl; si++)
        memo[si] = true;
    } else {
      for (si = sl - 1; si >= 0; si--)
        memo[si + 1] = memo[si] && isMatch(s[si], p[pi]);
    }
    memo[0] = memo[0] && p[pi] == '*';
  }

  return memo[sl];
}
#endif

bool WildcardMatching::isMatch(string s, string p)
{
  int ns = s.size();
  int np = p.size();

  vector<vector<bool>> dp(ns + 1, vector<bool>(np + 1, false));
  dp[0][0] = true;

  for (int i = 1; i <= ns; i++)
    dp[i][0] = false;

  for (int j = 1; j <= np; j++)
    dp[0][j] = dp[0][j-1] && p[j-1] == '*';

  for (int i = 1; i <= ns; i++) {
    for (int j = 1; j <= np; j++) {
      if (p[j-1] != '*')
        dp[i][j] = dp[i-1][j-1] && isMatch(s[i-1], p[j-1]);
      else
        dp[i][j] = dp[i-1][j] || dp[i][j-1];
    }
  }

  return dp[ns][np];
}

bool WildcardMatching::isMatch(char c, char p)
{
  return p == '?' || c == p;
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "ElemElement.hpp"

#include <sax/AttributeList.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "AVT.hpp"
#include "Constants.hpp"
#include "Stylesheet.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"

ElemElement::ElemElement(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemUse(constructionContext,
			stylesheetTree,
			lineNumber,
			columnNumber,
			Constants::ELEMNAME_ELEMENT),
	m_nameAVT(0),
	m_namespaceAVT(0)
{
	// Namespace aliases are not used for xsl:element, so
	// turn them off...
	m_namespacesHandler.setProcessNamespaceAliaises(false);

	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar*	const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_NAME))
		{
			m_nameAVT = new AVT(getLocator(), aname,	atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(equals(aname, Constants::ATTRNAME_NAMESPACE))
		{
			m_namespaceAVT = new AVT(getLocator(), aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(!(processUseAttributeSets(constructionContext, aname, atts, i) ||
			    processSpaceAttr(aname, atts, i, constructionContext) ||
				isAttrOK(aname, atts, i, constructionContext)))
		{
			constructionContext.error(Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING + " has an illegal attribute: " + aname);
		}
	}

	if(0 == m_nameAVT)
	{
		constructionContext.error(
			"xsl:element must have a 'name' attribute.",
			0,
			this);
	}

}

ElemElement::~ElemElement()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete (AVT*)m_nameAVT;

	delete (AVT*)m_namespaceAVT;
#else
	delete m_nameAVT;

	delete m_namespaceAVT;
#endif
}

const XalanDOMString&
ElemElement::getElementName() const
{
	return Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING;
}

void
ElemElement::execute(StylesheetExecutionContext&		executionContext) const
{
	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameGuard(executionContext);

	XalanDOMString&		elemName = elemNameGuard.get();

	XalanNode* const	sourceNode = executionContext.getCurrentNode();

	m_nameAVT->evaluate(elemName, sourceNode, *this, executionContext);

	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameSpaceGuard(executionContext);

	XalanDOMString&		elemNameSpace = elemNameSpaceGuard.get();

	if (m_namespaceAVT != 0)
	{
		m_namespaceAVT->evaluate(elemNameSpace, sourceNode, *this, executionContext);
	}

	XalanDOMString::size_type	namespaceLen = length(elemNameSpace);

	bool	isIllegalElement = false;

	bool	hasUnresolvedPrefix = false;

	XalanDOMString::size_type			len = length(elemName);

	const XalanDOMString::size_type		indexOfNSSep = indexOf(elemName, XalanUnicode::charColon);

	const bool	haveNamespace = indexOfNSSep == len ? false : true;

	StylesheetExecutionContext::GetAndReleaseCachedString	prefixGuard(executionContext);

	XalanDOMString&		prefix = prefixGuard.get();

	if(haveNamespace == true)
	{
		if (indexOfNSSep + 1 == len ||
			isValidNCName(substring(elemName, indexOfNSSep + 1)) == false)
		{
			isIllegalElement = true;
		}
	}
	else if(len == 0 || isValidNCName(elemName) == false)
	{
		isIllegalElement = true;
	}

	if (isIllegalElement == true)
	{
		executionContext.warn("Illegal element name: \"" + elemName + "\"", this, sourceNode);

		clear(elemName);
	}
	else if (haveNamespace == true)
	{
		prefix = substring(elemName, 0, indexOfNSSep);

		const XalanDOMString* const		theNamespace =
			executionContext.getResultNamespaceForPrefix(prefix);

		if (theNamespace == 0)
		{
			const XalanDOMString* const		theNamespace =
				m_namespacesHandler.getNamespace(prefix);

			if(theNamespace == 0 && namespaceLen == 0)
			{
				executionContext.warn("Could not resolve prefix: " + prefix, this, sourceNode);

				if (m_namespaceAVT != 0)
				{
					hasUnresolvedPrefix = true;

					elemName = substring(elemName, indexOfNSSep + 1);
				}
				else
				{
					isIllegalElement = true;
				}
			}
		}
	}

	if (isIllegalElement == false)
	{
		executionContext.startElement(c_wstr(elemName));

		if(0 == m_namespaceAVT)
		{
			outputResultNamespaces(executionContext, hasUnresolvedPrefix);
		}
		else
		{
			if(namespaceLen == 0 && hasUnresolvedPrefix == true)
			{
				outputResultNamespaces(
					executionContext,
					hasUnresolvedPrefix,
					length(getParentDefaultNamespace()) == 0 ? true : false);
			}
			else
			{
				if(haveNamespace == false)
				{
					if (namespaceLen > 0)
					{
						outputResultNamespaces(executionContext, hasUnresolvedPrefix);

						executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
					}
					else
					{
						// OK, the namespace we're generating is the default namespace,
						// so let's make sure that we really need it.  If we don't,
						// we end up with another xmlns="" on the element we're
						// generating.  Although this isn't really an error, it's
						// a bit unsightly, so let's suppress it...
						const XalanDOMString&	theParentDefaultNamespace =
							getParentDefaultNamespace();

						if (length(theParentDefaultNamespace) == 0)
						{
							// There's not default namespace in effect, so suppress any
							// default namespace in the statically-generated namespaces,
							// and don't put out the one we've dynamically generated...
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, true);
						}
						else
						{
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, false);

							executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
						}
					}
				}
				else
				{
					outputResultNamespaces(executionContext, hasUnresolvedPrefix);

					const XalanDOMString* const		theNamespace =
						executionContext.getResultNamespaceForPrefix(prefix);

					if (theNamespace == 0 ||
						equals(*theNamespace, elemNameSpace) == false)
					{
						insert(prefix, 0, DOMServices::s_XMLNamespaceWithSeparator);

						executionContext.addResultAttribute(prefix, elemNameSpace);
					}
				}
			}
		}
	}

	ElemUse::execute(executionContext);

	doExecuteChildren(executionContext, isIllegalElement);

	if (isIllegalElement == false)
	{
		executionContext.endElement(c_wstr(elemName));
	}
}

void
ElemElement::doExecuteChildren(
			StylesheetExecutionContext&		executionContext,
			bool							skipAttributeChildren) const
{
	if (skipAttributeChildren == false)
	{
		// If we should execute all children, then just call
		// executeChildren()...
		executeChildren(executionContext);
	}
	else
	{
		StylesheetExecutionContext::PushAndPopElementFrame	thePushAndPop(executionContext, this);

		for (ElemTemplateElement* node = getFirstChildElem(); node != 0; node = node->getNextSiblingElem())
		{
			if (node->getXSLToken() != Constants::ELEMNAME_ATTRIBUTE)
			{
				node->execute(executionContext);
			}
		}
	}
}

void
ElemElement::outputResultNamespaces(
			StylesheetExecutionContext&		executionContext,
			bool							hasUnresolvedPrefix,
			bool							supressDefault) const
{
	m_namespacesHandler.outputResultNamespaces(executionContext, supressDefault);

	if (supressDefault == false)
	{
		// OK, now let's check to make sure we don't have to change the default namespace...
		const XalanDOMString* const		theCurrentDefaultNamespace =
					executionContext.getResultNamespaceForPrefix(s_emptyString);

		if (theCurrentDefaultNamespace != 0)
		{
			const XalanDOMString* const		theElementDefaultNamespace =
						m_namespacesHandler.getNamespace(s_emptyString);

			if (hasUnresolvedPrefix == true || theElementDefaultNamespace == 0)
			{
				// There was no default namespace, so we have to turn the
				// current one off.
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, s_emptyString);
			}
			else if (equals(*theCurrentDefaultNamespace, *theElementDefaultNamespace) == false)
			{
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, *theElementDefaultNamespace);
			}
		}
	}
}

const XalanDOMString&
ElemElement::getParentDefaultNamespace() const
{
	const ElemTemplateElement* const	theParent =
		getParentNodeElem();

	if (theParent == 0)
	{
		return s_emptyString;
	}
	else
	{
		const XalanDOMString* const		theParentDefaultNamespace =
						theParent->getNamespacesHandler().getNamespace(s_emptyString);

		if (theParentDefaultNamespace == 0)
		{
			return s_emptyString;
		}
		else
		{
			return *theParentDefaultNamespace;
		}
	}
}
<commit_msg>Fix for namespace89.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "ElemElement.hpp"

#include <sax/AttributeList.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "AVT.hpp"
#include "Constants.hpp"
#include "Stylesheet.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"

ElemElement::ElemElement(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemUse(constructionContext,
			stylesheetTree,
			lineNumber,
			columnNumber,
			Constants::ELEMNAME_ELEMENT),
	m_nameAVT(0),
	m_namespaceAVT(0)
{
	// Namespace aliases are not used for xsl:element, so
	// turn them off...
	m_namespacesHandler.setProcessNamespaceAliaises(false);

	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar*	const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_NAME))
		{
			m_nameAVT = new AVT(getLocator(), aname,	atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(equals(aname, Constants::ATTRNAME_NAMESPACE))
		{
			m_namespaceAVT = new AVT(getLocator(), aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(!(processUseAttributeSets(constructionContext, aname, atts, i) ||
			    processSpaceAttr(aname, atts, i, constructionContext) ||
				isAttrOK(aname, atts, i, constructionContext)))
		{
			constructionContext.error(Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING + " has an illegal attribute: " + aname);
		}
	}

	if(0 == m_nameAVT)
	{
		constructionContext.error(
			"xsl:element must have a 'name' attribute.",
			0,
			this);
	}

}

ElemElement::~ElemElement()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete (AVT*)m_nameAVT;

	delete (AVT*)m_namespaceAVT;
#else
	delete m_nameAVT;

	delete m_namespaceAVT;
#endif
}

const XalanDOMString&
ElemElement::getElementName() const
{
	return Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING;
}

void
ElemElement::execute(StylesheetExecutionContext&		executionContext) const
{
	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameGuard(executionContext);

	XalanDOMString&		elemName = elemNameGuard.get();

	XalanNode* const	sourceNode = executionContext.getCurrentNode();

	m_nameAVT->evaluate(elemName, sourceNode, *this, executionContext);

	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameSpaceGuard(executionContext);

	XalanDOMString&		elemNameSpace = elemNameSpaceGuard.get();

	if (m_namespaceAVT != 0)
	{
		m_namespaceAVT->evaluate(elemNameSpace, sourceNode, *this, executionContext);
	}

	XalanDOMString::size_type	namespaceLen = length(elemNameSpace);

	bool	isIllegalElement = false;

	bool	hasUnresolvedPrefix = false;

	bool	foundResultNamespaceForPrefix = false;

	XalanDOMString::size_type			len = length(elemName);

	const XalanDOMString::size_type		indexOfNSSep = indexOf(elemName, XalanUnicode::charColon);

	const bool	haveNamespace = indexOfNSSep == len ? false : true;

	StylesheetExecutionContext::GetAndReleaseCachedString	prefixGuard(executionContext);

	XalanDOMString&		prefix = prefixGuard.get();

	if(haveNamespace == true)
	{
		if (indexOfNSSep + 1 == len ||
			isValidNCName(substring(elemName, indexOfNSSep + 1)) == false)
		{
			isIllegalElement = true;
		}
	}
	else if(len == 0 || isValidNCName(elemName) == false)
	{
		isIllegalElement = true;
	}

	if (isIllegalElement == true)
	{
		executionContext.warn("Illegal element name: \"" + elemName + "\"", this, sourceNode);

		clear(elemName);
	}
	else if (haveNamespace == true)
	{
		prefix = substring(elemName, 0, indexOfNSSep);

		const XalanDOMString* const		theNamespace =
			executionContext.getResultNamespaceForPrefix(prefix);

		if (theNamespace != 0)
		{
			foundResultNamespaceForPrefix = true;
		}
		else
		{
			const XalanDOMString* const		theNamespace =
				m_namespacesHandler.getNamespace(prefix);

			if(theNamespace == 0 && namespaceLen == 0)
			{
				executionContext.warn("Could not resolve prefix: " + prefix, this, sourceNode);

				if (m_namespaceAVT != 0)
				{
					hasUnresolvedPrefix = true;

					elemName = substring(elemName, indexOfNSSep + 1);
				}
				else
				{
					isIllegalElement = true;
				}
			}
			else if (theNamespace != 0 &&
					 namespaceLen == 0 &&
					 equals(prefix, DOMServices::s_XMLNamespace) == false)
			{
				elemNameSpace = *theNamespace;
			}
		}
	}

	if (isIllegalElement == false)
	{
		executionContext.startElement(c_wstr(elemName));

		if(0 == m_namespaceAVT &&
		   (haveNamespace == false || foundResultNamespaceForPrefix == true))
		{
			outputResultNamespaces(executionContext, hasUnresolvedPrefix);
		}
		else
		{
			if(namespaceLen == 0 && hasUnresolvedPrefix == true)
			{
				outputResultNamespaces(
					executionContext,
					hasUnresolvedPrefix,
					length(getParentDefaultNamespace()) == 0 ? true : false);
			}
			else
			{
				if(haveNamespace == false)
				{
					if (namespaceLen > 0)
					{
						outputResultNamespaces(executionContext, hasUnresolvedPrefix);

						executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
					}
					else
					{
						// OK, the namespace we're generating is the default namespace,
						// so let's make sure that we really need it.  If we don't,
						// we end up with another xmlns="" on the element we're
						// generating.  Although this isn't really an error, it's
						// a bit unsightly, so let's suppress it...
						const XalanDOMString&	theParentDefaultNamespace =
							getParentDefaultNamespace();

						if (length(theParentDefaultNamespace) == 0)
						{
							// There's not default namespace in effect, so suppress any
							// default namespace in the statically-generated namespaces,
							// and don't put out the one we've dynamically generated...
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, true);
						}
						else
						{
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, false);

							executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
						}
					}
				}
				else
				{
					outputResultNamespaces(executionContext, hasUnresolvedPrefix);

					const XalanDOMString* const		theNamespace =
						executionContext.getResultNamespaceForPrefix(prefix);

					if (theNamespace == 0 ||
						equals(*theNamespace, elemNameSpace) == false)
					{
						insert(prefix, 0, DOMServices::s_XMLNamespaceWithSeparator);

						executionContext.addResultAttribute(prefix, elemNameSpace);
					}
				}
			}
		}
	}

	ElemUse::execute(executionContext);

	doExecuteChildren(executionContext, isIllegalElement);

	if (isIllegalElement == false)
	{
		executionContext.endElement(c_wstr(elemName));
	}
}

void
ElemElement::doExecuteChildren(
			StylesheetExecutionContext&		executionContext,
			bool							skipAttributeChildren) const
{
	if (skipAttributeChildren == false)
	{
		// If we should execute all children, then just call
		// executeChildren()...
		executeChildren(executionContext);
	}
	else
	{
		StylesheetExecutionContext::PushAndPopElementFrame	thePushAndPop(executionContext, this);

		for (ElemTemplateElement* node = getFirstChildElem(); node != 0; node = node->getNextSiblingElem())
		{
			if (node->getXSLToken() != Constants::ELEMNAME_ATTRIBUTE)
			{
				node->execute(executionContext);
			}
		}
	}
}

void
ElemElement::outputResultNamespaces(
			StylesheetExecutionContext&		executionContext,
			bool							hasUnresolvedPrefix,
			bool							supressDefault) const
{
	m_namespacesHandler.outputResultNamespaces(executionContext, supressDefault);

	if (supressDefault == false)
	{
		// OK, now let's check to make sure we don't have to change the default namespace...
		const XalanDOMString* const		theCurrentDefaultNamespace =
					executionContext.getResultNamespaceForPrefix(s_emptyString);

		if (theCurrentDefaultNamespace != 0)
		{
			const XalanDOMString* const		theElementDefaultNamespace =
						m_namespacesHandler.getNamespace(s_emptyString);

			if (hasUnresolvedPrefix == true || theElementDefaultNamespace == 0)
			{
				// There was no default namespace, so we have to turn the
				// current one off.
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, s_emptyString);
			}
			else if (equals(*theCurrentDefaultNamespace, *theElementDefaultNamespace) == false)
			{
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, *theElementDefaultNamespace);
			}
		}
	}
}

const XalanDOMString&
ElemElement::getParentDefaultNamespace() const
{
	const ElemTemplateElement* const	theParent =
		getParentNodeElem();

	if (theParent == 0)
	{
		return s_emptyString;
	}
	else
	{
		const XalanDOMString* const		theParentDefaultNamespace =
						theParent->getNamespacesHandler().getNamespace(s_emptyString);

		if (theParentDefaultNamespace == 0)
		{
			return s_emptyString;
		}
		else
		{
			return *theParentDefaultNamespace;
		}
	}
}
<|endoftext|>


<commit_before>//===-- sanitizer_libc.cc -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries. See sanitizer_libc.h for details.
//===----------------------------------------------------------------------===//
#include "sanitizer_allocator_internal.h"
#include "sanitizer_common.h"
#include "sanitizer_libc.h"

namespace __sanitizer {

// Make the compiler think that something is going on there.
static inline void break_optimization(void *arg) {
#ifdef SANITIZER_WINDOWS
  // FIXME: make sure this is actually enough.
  __asm;
#else
  __asm__ __volatile__("" : : "r" (arg) : "memory");
#endif
}

s64 internal_atoll(const char *nptr) {
  return internal_simple_strtoll(nptr, (char**)0, 10);
}

void *internal_memchr(const void *s, int c, uptr n) {
  const char* t = (char*)s;
  for (uptr i = 0; i < n; ++i, ++t)
    if (*t == c)
      return (void*)t;
  return 0;
}

int internal_memcmp(const void* s1, const void* s2, uptr n) {
  const char* t1 = (char*)s1;
  const char* t2 = (char*)s2;
  for (uptr i = 0; i < n; ++i, ++t1, ++t2)
    if (*t1 != *t2)
      return *t1 < *t2 ? -1 : 1;
  return 0;
}

void *internal_memcpy(void *dest, const void *src, uptr n) {
  char *d = (char*)dest;
  char *s = (char*)src;
  for (uptr i = 0; i < n; ++i)
    d[i] = s[i];
  return dest;
}

void *internal_memmove(void *dest, const void *src, uptr n) {
  char *d = (char*)dest;
  char *s = (char*)src;
  sptr i, signed_n = (sptr)n;
  CHECK_GE(signed_n, 0);
  if (d < s) {
    for (i = 0; i < signed_n; ++i)
      d[i] = s[i];
  } else {
    if (d > s && signed_n > 0)
      for (i = signed_n - 1; i >= 0 ; --i) {
        d[i] = s[i];
      }
  }
  return dest;
}

// Semi-fast bzero for 16-aligned data. Still far from peak performance.
void internal_bzero_aligned16(void *s, uptr n) {
  struct S16 { u64 a, b; } ALIGNED(16);
  CHECK_EQ((reinterpret_cast<uptr>(s) | n) & 15, 0);
  for (S16 *p = reinterpret_cast<S16*>(s), *end = p + n / 16; p < end; p++) {
    p->a = p->b = 0;
    break_optimization(0);  // Make sure this does not become memset.
  }
}

void *internal_memset(void* s, int c, uptr n) {
  // The next line prevents Clang from making a call to memset() instead of the
  // loop below.
  // FIXME: building the runtime with -ffreestanding is a better idea. However
  // there currently are linktime problems due to PR12396.
  char volatile *t = (char*)s;
  for (uptr i = 0; i < n; ++i, ++t) {
    *t = c;
  }
  return s;
}

uptr internal_strcspn(const char *s, const char *reject) {
  uptr i;
  for (i = 0; s[i]; i++) {
    if (internal_strchr(reject, s[i]) != 0)
      return i;
  }
  return i;
}

char* internal_strdup(const char *s) {
  uptr len = internal_strlen(s);
  char *s2 = (char*)InternalAlloc(len + 1);
  internal_memcpy(s2, s, len);
  s2[len] = 0;
  return s2;
}

int internal_strcmp(const char *s1, const char *s2) {
  while (true) {
    unsigned c1 = *s1;
    unsigned c2 = *s2;
    if (c1 != c2) return (c1 < c2) ? -1 : 1;
    if (c1 == 0) break;
    s1++;
    s2++;
  }
  return 0;
}

int internal_strncmp(const char *s1, const char *s2, uptr n) {
  for (uptr i = 0; i < n; i++) {
    unsigned c1 = *s1;
    unsigned c2 = *s2;
    if (c1 != c2) return (c1 < c2) ? -1 : 1;
    if (c1 == 0) break;
    s1++;
    s2++;
  }
  return 0;
}

char* internal_strchr(const char *s, int c) {
  while (true) {
    if (*s == (char)c)
      return (char*)s;
    if (*s == 0)
      return 0;
    s++;
  }
}

char *internal_strchrnul(const char *s, int c) {
  char *res = internal_strchr(s, c);
  if (!res)
    res = (char*)s + internal_strlen(s);
  return res;
}

char *internal_strrchr(const char *s, int c) {
  const char *res = 0;
  for (uptr i = 0; s[i]; i++) {
    if (s[i] == c) res = s + i;
  }
  return (char*)res;
}

uptr internal_strlen(const char *s) {
  uptr i = 0;
  while (s[i]) i++;
  return i;
}

char *internal_strncat(char *dst, const char *src, uptr n) {
  uptr len = internal_strlen(dst);
  uptr i;
  for (i = 0; i < n && src[i]; i++)
    dst[len + i] = src[i];
  dst[len + i] = 0;
  return dst;
}

char *internal_strncpy(char *dst, const char *src, uptr n) {
  uptr i;
  for (i = 0; i < n && src[i]; i++)
    dst[i] = src[i];
  internal_memset(dst + i, '\0', n - i);
  return dst;
}

uptr internal_strnlen(const char *s, uptr maxlen) {
  uptr i = 0;
  while (i < maxlen && s[i]) i++;
  return i;
}

char *internal_strstr(const char *haystack, const char *needle) {
  // This is O(N^2), but we are not using it in hot places.
  uptr len1 = internal_strlen(haystack);
  uptr len2 = internal_strlen(needle);
  if (len1 < len2) return 0;
  for (uptr pos = 0; pos <= len1 - len2; pos++) {
    if (internal_memcmp(haystack + pos, needle, len2) == 0)
      return (char*)haystack + pos;
  }
  return 0;
}

s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
  CHECK_EQ(base, 10);
  while (IsSpace(*nptr)) nptr++;
  int sgn = 1;
  u64 res = 0;
  bool have_digits = false;
  char *old_nptr = (char*)nptr;
  if (*nptr == '+') {
    sgn = 1;
    nptr++;
  } else if (*nptr == '-') {
    sgn = -1;
    nptr++;
  }
  while (IsDigit(*nptr)) {
    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
    int digit = ((*nptr) - '0');
    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
    have_digits = true;
    nptr++;
  }
  if (endptr != 0) {
    *endptr = (have_digits) ? (char*)nptr : old_nptr;
  }
  if (sgn > 0) {
    return (s64)(Min((u64)INT64_MAX, res));
  } else {
    return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
  }
}

bool mem_is_zero(const char *beg, uptr size) {
  CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
  const char *end = beg + size;
  uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
  uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
  uptr all = 0;
  // Prologue.
  for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
    all |= *mem;
  // Aligned loop.
  for (; aligned_beg < aligned_end; aligned_beg++)
    all |= *aligned_beg;
  // Epilogue.
  if ((char*)aligned_end >= beg)
    for (const char *mem = (char*)aligned_end; mem < end; mem++)
      all |= *mem;
  return all == 0;
}

}  // namespace __sanitizer
<commit_msg>[ASan] Follow-up fix: use #if SANITIZER_WINDOWS, not #ifdef<commit_after>//===-- sanitizer_libc.cc -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries. See sanitizer_libc.h for details.
//===----------------------------------------------------------------------===//
#include "sanitizer_allocator_internal.h"
#include "sanitizer_common.h"
#include "sanitizer_libc.h"

namespace __sanitizer {

// Make the compiler think that something is going on there.
static inline void break_optimization(void *arg) {
#if SANITIZER_WINDOWS
  // FIXME: make sure this is actually enough.
  __asm;
#else
  __asm__ __volatile__("" : : "r" (arg) : "memory");
#endif
}

s64 internal_atoll(const char *nptr) {
  return internal_simple_strtoll(nptr, (char**)0, 10);
}

void *internal_memchr(const void *s, int c, uptr n) {
  const char* t = (char*)s;
  for (uptr i = 0; i < n; ++i, ++t)
    if (*t == c)
      return (void*)t;
  return 0;
}

int internal_memcmp(const void* s1, const void* s2, uptr n) {
  const char* t1 = (char*)s1;
  const char* t2 = (char*)s2;
  for (uptr i = 0; i < n; ++i, ++t1, ++t2)
    if (*t1 != *t2)
      return *t1 < *t2 ? -1 : 1;
  return 0;
}

void *internal_memcpy(void *dest, const void *src, uptr n) {
  char *d = (char*)dest;
  char *s = (char*)src;
  for (uptr i = 0; i < n; ++i)
    d[i] = s[i];
  return dest;
}

void *internal_memmove(void *dest, const void *src, uptr n) {
  char *d = (char*)dest;
  char *s = (char*)src;
  sptr i, signed_n = (sptr)n;
  CHECK_GE(signed_n, 0);
  if (d < s) {
    for (i = 0; i < signed_n; ++i)
      d[i] = s[i];
  } else {
    if (d > s && signed_n > 0)
      for (i = signed_n - 1; i >= 0 ; --i) {
        d[i] = s[i];
      }
  }
  return dest;
}

// Semi-fast bzero for 16-aligned data. Still far from peak performance.
void internal_bzero_aligned16(void *s, uptr n) {
  struct S16 { u64 a, b; } ALIGNED(16);
  CHECK_EQ((reinterpret_cast<uptr>(s) | n) & 15, 0);
  for (S16 *p = reinterpret_cast<S16*>(s), *end = p + n / 16; p < end; p++) {
    p->a = p->b = 0;
    break_optimization(0);  // Make sure this does not become memset.
  }
}

void *internal_memset(void* s, int c, uptr n) {
  // The next line prevents Clang from making a call to memset() instead of the
  // loop below.
  // FIXME: building the runtime with -ffreestanding is a better idea. However
  // there currently are linktime problems due to PR12396.
  char volatile *t = (char*)s;
  for (uptr i = 0; i < n; ++i, ++t) {
    *t = c;
  }
  return s;
}

uptr internal_strcspn(const char *s, const char *reject) {
  uptr i;
  for (i = 0; s[i]; i++) {
    if (internal_strchr(reject, s[i]) != 0)
      return i;
  }
  return i;
}

char* internal_strdup(const char *s) {
  uptr len = internal_strlen(s);
  char *s2 = (char*)InternalAlloc(len + 1);
  internal_memcpy(s2, s, len);
  s2[len] = 0;
  return s2;
}

int internal_strcmp(const char *s1, const char *s2) {
  while (true) {
    unsigned c1 = *s1;
    unsigned c2 = *s2;
    if (c1 != c2) return (c1 < c2) ? -1 : 1;
    if (c1 == 0) break;
    s1++;
    s2++;
  }
  return 0;
}

int internal_strncmp(const char *s1, const char *s2, uptr n) {
  for (uptr i = 0; i < n; i++) {
    unsigned c1 = *s1;
    unsigned c2 = *s2;
    if (c1 != c2) return (c1 < c2) ? -1 : 1;
    if (c1 == 0) break;
    s1++;
    s2++;
  }
  return 0;
}

char* internal_strchr(const char *s, int c) {
  while (true) {
    if (*s == (char)c)
      return (char*)s;
    if (*s == 0)
      return 0;
    s++;
  }
}

char *internal_strchrnul(const char *s, int c) {
  char *res = internal_strchr(s, c);
  if (!res)
    res = (char*)s + internal_strlen(s);
  return res;
}

char *internal_strrchr(const char *s, int c) {
  const char *res = 0;
  for (uptr i = 0; s[i]; i++) {
    if (s[i] == c) res = s + i;
  }
  return (char*)res;
}

uptr internal_strlen(const char *s) {
  uptr i = 0;
  while (s[i]) i++;
  return i;
}

char *internal_strncat(char *dst, const char *src, uptr n) {
  uptr len = internal_strlen(dst);
  uptr i;
  for (i = 0; i < n && src[i]; i++)
    dst[len + i] = src[i];
  dst[len + i] = 0;
  return dst;
}

char *internal_strncpy(char *dst, const char *src, uptr n) {
  uptr i;
  for (i = 0; i < n && src[i]; i++)
    dst[i] = src[i];
  internal_memset(dst + i, '\0', n - i);
  return dst;
}

uptr internal_strnlen(const char *s, uptr maxlen) {
  uptr i = 0;
  while (i < maxlen && s[i]) i++;
  return i;
}

char *internal_strstr(const char *haystack, const char *needle) {
  // This is O(N^2), but we are not using it in hot places.
  uptr len1 = internal_strlen(haystack);
  uptr len2 = internal_strlen(needle);
  if (len1 < len2) return 0;
  for (uptr pos = 0; pos <= len1 - len2; pos++) {
    if (internal_memcmp(haystack + pos, needle, len2) == 0)
      return (char*)haystack + pos;
  }
  return 0;
}

s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
  CHECK_EQ(base, 10);
  while (IsSpace(*nptr)) nptr++;
  int sgn = 1;
  u64 res = 0;
  bool have_digits = false;
  char *old_nptr = (char*)nptr;
  if (*nptr == '+') {
    sgn = 1;
    nptr++;
  } else if (*nptr == '-') {
    sgn = -1;
    nptr++;
  }
  while (IsDigit(*nptr)) {
    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
    int digit = ((*nptr) - '0');
    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
    have_digits = true;
    nptr++;
  }
  if (endptr != 0) {
    *endptr = (have_digits) ? (char*)nptr : old_nptr;
  }
  if (sgn > 0) {
    return (s64)(Min((u64)INT64_MAX, res));
  } else {
    return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
  }
}

bool mem_is_zero(const char *beg, uptr size) {
  CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
  const char *end = beg + size;
  uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
  uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
  uptr all = 0;
  // Prologue.
  for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
    all |= *mem;
  // Aligned loop.
  for (; aligned_beg < aligned_end; aligned_beg++)
    all |= *aligned_beg;
  // Epilogue.
  if ((char*)aligned_end >= beg)
    for (const char *mem = (char*)aligned_end; mem < end; mem++)
      all |= *mem;
  return all == 0;
}

}  // namespace __sanitizer
<|endoftext|>


<commit_before>//
//  InstructionOperandFlags.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 09/05/2022.
//  Copyright © 2022 Thomas Harte. All rights reserved.
//

#ifndef InstructionSets_68k_InstructionOperandFlags_hpp
#define InstructionSets_68k_InstructionOperandFlags_hpp

namespace InstructionSet {
namespace M68k {

template <Model model, Operation t_operation> constexpr uint8_t operand_flags(Operation r_operation) {
	switch((t_operation != Operation::Undefined) ? t_operation : r_operation) {
		default:
			assert(false);

		//
		//	No operands are fetched or stored.
		//	(which means that source and destination will appear as their effective addresses)
		//
		case Operation::PEA:
		case Operation::JMP:		case Operation::JSR:
		case Operation::MOVEPw:		case Operation::MOVEPl:
		case Operation::MOVEMtoMw:	case Operation::MOVEMtoMl:
		case Operation::MOVEMtoRw:	case Operation::MOVEMtoRl:
		case Operation::TAS:
		case Operation::RTR:		case Operation::RTS:		case Operation::RTE:
			return 0;

		//
		//	Single-operand read.
		//
		case Operation::MOVEtoSR:	case Operation::MOVEtoCCR:	case Operation::MOVEtoUSP:
		case Operation::ORItoSR:	case Operation::ORItoCCR:
		case Operation::ANDItoSR:	case Operation::ANDItoCCR:
		case Operation::EORItoSR:	case Operation::EORItoCCR:
		case Operation::Bccb:		case Operation::Bccw:		case Operation::Bccl:
		case Operation::BSRb:		case Operation::BSRw:		case Operation::BSRl:
		case Operation::TSTb:		case Operation::TSTw:		case Operation::TSTl:
			return FetchOp1;

		//
		//	Single-operand write.
		//
		case Operation::MOVEfromSR:	case Operation::MOVEfromUSP:
			return StoreOp1;

		//
		//	Single-operand read-modify-write.
		//
		case Operation::NBCD:
		case Operation::NOTb:		case Operation::NOTw:		case Operation::NOTl:
		case Operation::NEGb:		case Operation::NEGw:		case Operation::NEGl:
		case Operation::NEGXb:		case Operation::NEGXw:		case Operation::NEGXl:
		case Operation::EXTbtow:	case Operation::EXTwtol:
		case Operation::SWAP:
		case Operation::UNLINK:
		case Operation::ASLm:		case Operation::ASRm:
		case Operation::LSLm:		case Operation::LSRm:
		case Operation::ROLm:		case Operation::RORm:
		case Operation::ROXLm:		case Operation::ROXRm:
		case Operation::Scc:
			return FetchOp1 | StoreOp1;

		//
		//	CLR, which is model-dependent.
		//
		case Operation::CLRb:	case Operation::CLRw:	case Operation::CLRl:
			if constexpr (model == Model::M68000) {
				return FetchOp1 | StoreOp1;
			} else {
				return StoreOp1;
			}

		//
		//	Two-operand; read both.
		//
		case Operation::CMPb:	case Operation::CMPw:	case Operation::CMPl:
		case Operation::CMPAw:	case Operation::CMPAl:
		case Operation::CHK:
		case Operation::BTST:
		case Operation::LINKw:
			return FetchOp1 | FetchOp2;

		//
		//	Two-operand; read source, write dest.
		//
		case Operation::MOVEb: 	case Operation::MOVEw: 	case Operation::MOVEl:
		case Operation::MOVEAw:	case Operation::MOVEAl:
			return FetchOp1 | StoreOp2;

		//
		//	Two-operand; read both, write dest.
		//
		case Operation::ABCD:	case Operation::SBCD:
		case Operation::ADDb: 	case Operation::ADDw: 	case Operation::ADDl:
		case Operation::ADDAw:	case Operation::ADDAl:
		case Operation::ADDXb: 	case Operation::ADDXw: 	case Operation::ADDXl:
		case Operation::SUBb: 	case Operation::SUBw: 	case Operation::SUBl:
		case Operation::SUBAw:	case Operation::SUBAl:
		case Operation::SUBXb: 	case Operation::SUBXw: 	case Operation::SUBXl:
		case Operation::ORb:	case Operation::ORw:	case Operation::ORl:
		case Operation::ANDb:	case Operation::ANDw:	case Operation::ANDl:
		case Operation::EORb:	case Operation::EORw:	case Operation::EORl:
		case Operation::DIVU:	case Operation::DIVS:
		case Operation::MULU:	case Operation::MULS:
		case Operation::ASLb:	case Operation::ASLw:	case Operation::ASLl:
		case Operation::ASRb:	case Operation::ASRw:	case Operation::ASRl:
		case Operation::LSLb:	case Operation::LSLw:	case Operation::LSLl:
		case Operation::LSRb:	case Operation::LSRw:	case Operation::LSRl:
		case Operation::ROLb:	case Operation::ROLw:	case Operation::ROLl:
		case Operation::RORb:	case Operation::RORw:	case Operation::RORl:
		case Operation::ROXLb:	case Operation::ROXLw:	case Operation::ROXLl:
		case Operation::ROXRb:	case Operation::ROXRw:	case Operation::ROXRl:
		case Operation::BCHG:
		case Operation::BCLR:	case Operation::BSET:
			return FetchOp1 | FetchOp2 | StoreOp2;

		//
		// Two-operand; read both, write source.
		//
		case Operation::DBcc:
			return FetchOp1 | FetchOp2 | StoreOp1;

		//
		//	Two-operand; read both, write both.
		//
		case Operation::EXG:
			return FetchOp1 | FetchOp2 | StoreOp1 | StoreOp2;

		//
		//	Two-operand; just write destination.
		//
		case Operation::LEA:
			return StoreOp2;
	}
}

}
}

#endif /* InstructionSets_68k_InstructionOperandFlags_hpp */
<commit_msg>MOVEM has an immediate first operand.<commit_after>//
//  InstructionOperandFlags.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 09/05/2022.
//  Copyright © 2022 Thomas Harte. All rights reserved.
//

#ifndef InstructionSets_68k_InstructionOperandFlags_hpp
#define InstructionSets_68k_InstructionOperandFlags_hpp

namespace InstructionSet {
namespace M68k {

template <Model model, Operation t_operation> constexpr uint8_t operand_flags(Operation r_operation) {
	switch((t_operation != Operation::Undefined) ? t_operation : r_operation) {
		default:
			assert(false);

		//
		//	No operands are fetched or stored.
		//	(which means that source and destination will appear as their effective addresses)
		//
		case Operation::PEA:
		case Operation::JMP:		case Operation::JSR:
		case Operation::MOVEPw:		case Operation::MOVEPl:
		case Operation::TAS:
		case Operation::RTR:		case Operation::RTS:		case Operation::RTE:
			return 0;

		//
		//	Single-operand read.
		//
		case Operation::MOVEtoSR:	case Operation::MOVEtoCCR:	case Operation::MOVEtoUSP:
		case Operation::ORItoSR:	case Operation::ORItoCCR:
		case Operation::ANDItoSR:	case Operation::ANDItoCCR:
		case Operation::EORItoSR:	case Operation::EORItoCCR:
		case Operation::Bccb:		case Operation::Bccw:		case Operation::Bccl:
		case Operation::BSRb:		case Operation::BSRw:		case Operation::BSRl:
		case Operation::TSTb:		case Operation::TSTw:		case Operation::TSTl:
		case Operation::MOVEMtoMw:	case Operation::MOVEMtoMl:
		case Operation::MOVEMtoRw:	case Operation::MOVEMtoRl:
			return FetchOp1;

		//
		//	Single-operand write.
		//
		case Operation::MOVEfromSR:	case Operation::MOVEfromUSP:
			return StoreOp1;

		//
		//	Single-operand read-modify-write.
		//
		case Operation::NBCD:
		case Operation::NOTb:		case Operation::NOTw:		case Operation::NOTl:
		case Operation::NEGb:		case Operation::NEGw:		case Operation::NEGl:
		case Operation::NEGXb:		case Operation::NEGXw:		case Operation::NEGXl:
		case Operation::EXTbtow:	case Operation::EXTwtol:
		case Operation::SWAP:
		case Operation::UNLINK:
		case Operation::ASLm:		case Operation::ASRm:
		case Operation::LSLm:		case Operation::LSRm:
		case Operation::ROLm:		case Operation::RORm:
		case Operation::ROXLm:		case Operation::ROXRm:
		case Operation::Scc:
			return FetchOp1 | StoreOp1;

		//
		//	CLR, which is model-dependent.
		//
		case Operation::CLRb:	case Operation::CLRw:	case Operation::CLRl:
			if constexpr (model == Model::M68000) {
				return FetchOp1 | StoreOp1;
			} else {
				return StoreOp1;
			}

		//
		//	Two-operand; read both.
		//
		case Operation::CMPb:	case Operation::CMPw:	case Operation::CMPl:
		case Operation::CMPAw:	case Operation::CMPAl:
		case Operation::CHK:
		case Operation::BTST:
		case Operation::LINKw:
			return FetchOp1 | FetchOp2;

		//
		//	Two-operand; read source, write dest.
		//
		case Operation::MOVEb: 	case Operation::MOVEw: 	case Operation::MOVEl:
		case Operation::MOVEAw:	case Operation::MOVEAl:
			return FetchOp1 | StoreOp2;

		//
		//	Two-operand; read both, write dest.
		//
		case Operation::ABCD:	case Operation::SBCD:
		case Operation::ADDb: 	case Operation::ADDw: 	case Operation::ADDl:
		case Operation::ADDAw:	case Operation::ADDAl:
		case Operation::ADDXb: 	case Operation::ADDXw: 	case Operation::ADDXl:
		case Operation::SUBb: 	case Operation::SUBw: 	case Operation::SUBl:
		case Operation::SUBAw:	case Operation::SUBAl:
		case Operation::SUBXb: 	case Operation::SUBXw: 	case Operation::SUBXl:
		case Operation::ORb:	case Operation::ORw:	case Operation::ORl:
		case Operation::ANDb:	case Operation::ANDw:	case Operation::ANDl:
		case Operation::EORb:	case Operation::EORw:	case Operation::EORl:
		case Operation::DIVU:	case Operation::DIVS:
		case Operation::MULU:	case Operation::MULS:
		case Operation::ASLb:	case Operation::ASLw:	case Operation::ASLl:
		case Operation::ASRb:	case Operation::ASRw:	case Operation::ASRl:
		case Operation::LSLb:	case Operation::LSLw:	case Operation::LSLl:
		case Operation::LSRb:	case Operation::LSRw:	case Operation::LSRl:
		case Operation::ROLb:	case Operation::ROLw:	case Operation::ROLl:
		case Operation::RORb:	case Operation::RORw:	case Operation::RORl:
		case Operation::ROXLb:	case Operation::ROXLw:	case Operation::ROXLl:
		case Operation::ROXRb:	case Operation::ROXRw:	case Operation::ROXRl:
		case Operation::BCHG:
		case Operation::BCLR:	case Operation::BSET:
			return FetchOp1 | FetchOp2 | StoreOp2;

		//
		// Two-operand; read both, write source.
		//
		case Operation::DBcc:
			return FetchOp1 | FetchOp2 | StoreOp1;

		//
		//	Two-operand; read both, write both.
		//
		case Operation::EXG:
			return FetchOp1 | FetchOp2 | StoreOp1 | StoreOp2;

		//
		//	Two-operand; just write destination.
		//
		case Operation::LEA:
			return StoreOp2;
	}
}

}
}

#endif /* InstructionSets_68k_InstructionOperandFlags_hpp */
<|endoftext|>