<commit_before>#include <SDL2/SDL.h>
#include <iostream>
#include <core/mat4.h>
#include <render/init.h>
#include <render/debuggl.h>
#include <render/materialshader.h>
#include <memory>
#include <render/compiledmesh.h>
#include "render/shaderattribute3d.h"
#include "render/texture.h"
#include "core/filesystem.h"
#include "core/draw.h"
#include "core/random.h"
#include "core/shufflebag.h"
#include "render/world.h"
#include "render/viewport.h"
#include "render/camera.h"
#include "core/mat4.h"
#include "core/axisangle.h"
#include "core/aabb.h"

void SetupSdlOpenGlAttributes() {
  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_STEREO, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
  SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
}

class SdlTimer {
 public:
  SdlTimer()
      : current_time_(SDL_GetPerformanceCounter())
      , last_time_(0)
  { }

  float Update() {
    last_time_ = current_time_;
    current_time_ = SDL_GetPerformanceCounter();
    const float dt = (current_time_ - last_time_) * 1.0f / SDL_GetPerformanceFrequency();
    return dt;
  }

 private:
  Uint64 current_time_;
  Uint64 last_time_;
};

class Sdl {
 public:
  Sdl() : ok(false) {
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) {
      std::cerr << "Failed to init SDL: " << SDL_GetError() << "\n";
      return;
    }

    ok = true;
  }

  ~Sdl() {
    SDL_Quit();
  }

  bool ok;
};

class SdlWindow {
 public:
  SdlWindow(const std::string& title, int width, int height) : window(nullptr) {
    window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED,
                                          SDL_WINDOWPOS_UNDEFINED, width, height,
                                          SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    if (window == nullptr) {
      std::cerr << "Failed to create window " << SDL_GetError() << "\n";
    }
  }

  ~SdlWindow() {
    SDL_DestroyWindow(window);
  }

  SDL_Window* window;
};

class SdlGlContext {
 public:
  SdlGlContext(SdlWindow* window) : context(nullptr) {
    context = SDL_GL_CreateContext(window->window);
    if (context == nullptr) {
      std::cerr << "Failed to create GL context " << SDL_GetError() << "\n";
      return;
    }
  }

  ~SdlGlContext() {
    SDL_GL_DeleteContext(context);
  }

  SDL_GLContext context;
};

struct CubeAnimation
{
  CubeAnimation() : timer(0), from(quatf::Identity()), to(quatf::Identity()), rotation_speed(1.0f), move_speed(1.0f) {}

  std::shared_ptr<Actor> actor;
  float timer;
  quatf from;
  quatf to;
  float rotation_speed;
  float move_speed;
};

int main(int argc, char** argv) {
  Sdl sdl;
  if (sdl.ok == false) {
    return -1;
  }

  SetupSdlOpenGlAttributes();

  int width = 800;
  int height = 600;

  SdlWindow window {"Euphoria Demo", 800, 600};
  if (window.window == nullptr) {
    return -1;
  }

  SdlGlContext context {&window};

  if (context.context == nullptr) {
    return -1;
  }

  Init init;
  if (init.ok == false) {
    return -4;
  }

  SetupOpenglDebug();

  Viewport viewport { Recti::FromTopLeftWidthHeight(0,0, width, height) };
  viewport.Activate();

  FileSystem file_system;
  auto catalog = FileSystemRootCatalog::AddRoot(&file_system);
  FileSystemRootFolder::AddRoot(&file_system);
  catalog->RegisterFileString("default_shader.vert",
                              "#version 330 core\n"
                                  "in vec3 aPosition;\n"
                                  "in vec2 aTexCoord;\n"
                                  "\n"
                                  "out vec2 texCoord;\n"
                                  "\n"
                                  "uniform mat4 uProjection;\n"
                                  "uniform mat4 uView;\n"
                                  "uniform mat4 uModel;\n"
                                  "\n"
                                  "void main()\n"
                                  "{\n"
                                  "    gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);\n"
                                  "    texCoord = aTexCoord;\n"
                                  "}\n");
  catalog->RegisterFileString("default_shader.frag",
                              "#version 330 core\n"
                                  "out vec4 FragColor;\n"
                                  "\n"
                                  "in vec2 texCoord;\n"
                                  "\n"
                                  "uniform sampler2D uTexture;\n"
                                  "\n"
                                  "void main()\n"
                                  "{\n"
                                  "    FragColor = texture(uTexture, texCoord);\n"
                                  "}\n");

  MaterialShader shader;
  const bool shader_compile = shader.Load(&file_system, "default_shader");

  if(!shader_compile) {
    return -3;
  }

  auto texture_uniform = shader.shader_.GetUniform("uTexture");

  Image image;
  image.Setup(256, 256, false);
  Draw drawer{&image};
  const auto wi = drawer.WholeImage();
  drawer
      .Clear(Rgb::From(Color::Red));
  Random random {42};

  for(int i=0; i<20; i+= 1) {
    const auto color = Rgb::From(random.NextDawnbringerPalette());
    const auto pos = random.NextPoint(wi);
    const auto outer = random.NextRange(55.0f, 100.0f);
    const auto inner = random.NextRange(50.0f);
    drawer.Circle(color, pos, outer, 10, inner);
  }
  drawer
      .LineAntialiased(Rgb::From(Color::Black), wi.TopLeft(), wi.BottomRight())
      .LineAntialiased(Rgb::From(Color::Black), wi.BottomLeft(), wi.TopRight())
    .Text(wi.GetAbsoluteCenterPos(), "Hello world", Rgb::From(Color::Black), 2)
      ;
  catalog->RegisterFileData("image", image.Write(ImageWriteFormat::PNG));

  Texture2d texture;
  texture.LoadFromFile(&file_system, "image", AlphaLoad::Remove, Texture2dLoadData{});

  bool running = true;

  SdlTimer timer;

  World world;

  auto box = CompileMesh(meshes::CreateCube(0.5f));

  const float box_extent_value = 4;
  Aabb box_extents
    { vec3f{-box_extent_value, -box_extent_value, -box_extent_value},
      vec3f{box_extent_value, box_extent_value, box_extent_value} };

  std::vector<CubeAnimation> animation_handler;

  for(int i=0; i<20; ++i)
  {
    std::shared_ptr<Actor> actor = std::make_shared<Actor>(box);
    world.AddActor(actor);

    CubeAnimation anim;
    anim.actor = actor;
    anim.from = random.NextQuatf();
    anim.to = random.NextQuatf();
    anim.rotation_speed = random.NextRange(0.5f, 1.0f);
    anim.move_speed = random.NextRange(0.5f, 1.0f);
    anim.timer = random.NextFloat01();

    // generate a position not too close to the center
    vec3f position = vec3f::Origo();
    do {
      position = random.NextVec3(box_extents);
    } while(position.GetLength() < 1.4f);

    actor->SetPosition( position );
    actor->SetRotation( anim.from );

    animation_handler.push_back(anim);
  }

  Camera camera;
  camera.SetPosition(vec3f(0,0,3));

  while (running) {
    const float delta = timer.Update();

    for(auto& anim: animation_handler)
    {
      anim.timer += delta * anim.rotation_speed;
      int count = 0;
      while(anim.timer > 1.0f)
      {
        count += 1;
        anim.timer -= 1.0f;
        anim.from = anim.to;
        anim.to = random.NextQuatf();
        anim.rotation_speed = random.NextRange(0.3f, 1.0f);
        anim.move_speed = random.NextRange(0.5f, 1.0f);
      }
      Assert(count < 2);
      quatf q = quatf::SlerpShortway(anim.from, anim.timer, anim.to);
      anim.actor->SetRotation(q);
      const vec3f movement = q.In()*anim.move_speed*delta;
      const vec3f new_pos = box_extents.Wrap(anim.actor->GetPosition() + movement);
      anim.actor->SetPosition( new_pos );
    }

    SDL_Event e;
    while (SDL_PollEvent(&e) != 0) {
      switch (e.type) {
        case SDL_QUIT:
          running = false;
          break;
        case SDL_KEYDOWN:
        case SDL_KEYUP:
          {
            const bool down = e.type == SDL_KEYDOWN;
            switch( e.key.keysym.sym ) {
              case SDLK_ESCAPE:
                if(down) {
                  running = false;
                }
                break;
              default:
                // ignore other keys
                break;
            }
          }
          break;
        default:
          // ignore other events
          break;
      }
    }

    init.ClearScreen(Rgb::From(Color::DarkslateGray));
    shader.UseShader();
    BindTextureToShader(&texture, &shader.shader_, texture_uniform, 0);
    world.Render(viewport, camera, &shader);

    SDL_GL_SwapWindow(window.window);
  }

  return 0;
}

#if 0
class View {
Camera[] cameras;
};

class CameraView {
Camera;
ViewPort area; // glViewport
};

class Camera {
Mode mode;
World world;
culling info from world, created when camera is added to world
viewMatrix; // position + rotation
projectionMatrix; // ortho/perspective

// 4 planes from the projection matrix
getFrustum();

toViewSpace(); // camera space, eye space
toWorldSpace();
};

// normal, thermo optics/powerup
class Mode {
Pass[] passes;
};

class Pass {
tag/list
Shader shader;
};

class Shader {
material list: list of material names mapped to shader variables
};

class World {
Actor[] objects;
};

class Actor {
Mesh mesh;
position;
rotation;
modelMatrix;
ToLocalSpace();
ToWorldSpace();
};

class Mesh {
MeshPart[] meshParts;
};

class MeshPart {
Material material;
};

class MaterialList {
maps id, material name, shader variable
};

class Material {
Texture[] textures;
};
#endif
<commit_msg>a little bit more speed on the boxes<commit_after>#include <SDL2/SDL.h>
#include <iostream>
#include <core/mat4.h>
#include <render/init.h>
#include <render/debuggl.h>
#include <render/materialshader.h>
#include <memory>
#include <render/compiledmesh.h>
#include "render/shaderattribute3d.h"
#include "render/texture.h"
#include "core/filesystem.h"
#include "core/draw.h"
#include "core/random.h"
#include "core/shufflebag.h"
#include "render/world.h"
#include "render/viewport.h"
#include "render/camera.h"
#include "core/mat4.h"
#include "core/axisangle.h"
#include "core/aabb.h"

void SetupSdlOpenGlAttributes() {
  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 4);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);
  SDL_GL_SetAttribute(SDL_GL_STEREO, 0);
  SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
  SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
}

class SdlTimer {
 public:
  SdlTimer()
      : current_time_(SDL_GetPerformanceCounter())
      , last_time_(0)
  { }

  float Update() {
    last_time_ = current_time_;
    current_time_ = SDL_GetPerformanceCounter();
    const float dt = (current_time_ - last_time_) * 1.0f / SDL_GetPerformanceFrequency();
    return dt;
  }

 private:
  Uint64 current_time_;
  Uint64 last_time_;
};

class Sdl {
 public:
  Sdl() : ok(false) {
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) {
      std::cerr << "Failed to init SDL: " << SDL_GetError() << "\n";
      return;
    }

    ok = true;
  }

  ~Sdl() {
    SDL_Quit();
  }

  bool ok;
};

class SdlWindow {
 public:
  SdlWindow(const std::string& title, int width, int height) : window(nullptr) {
    window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED,
                                          SDL_WINDOWPOS_UNDEFINED, width, height,
                                          SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    if (window == nullptr) {
      std::cerr << "Failed to create window " << SDL_GetError() << "\n";
    }
  }

  ~SdlWindow() {
    SDL_DestroyWindow(window);
  }

  SDL_Window* window;
};

class SdlGlContext {
 public:
  SdlGlContext(SdlWindow* window) : context(nullptr) {
    context = SDL_GL_CreateContext(window->window);
    if (context == nullptr) {
      std::cerr << "Failed to create GL context " << SDL_GetError() << "\n";
      return;
    }
  }

  ~SdlGlContext() {
    SDL_GL_DeleteContext(context);
  }

  SDL_GLContext context;
};

struct CubeAnimation
{
  CubeAnimation() : timer(0), from(quatf::Identity()), to(quatf::Identity()), rotation_speed(1.0f), move_speed(1.0f) {}

  std::shared_ptr<Actor> actor;
  float timer;
  quatf from;
  quatf to;
  float rotation_speed;
  float move_speed;
};

int main(int argc, char** argv) {
  Sdl sdl;
  if (sdl.ok == false) {
    return -1;
  }

  SetupSdlOpenGlAttributes();

  int width = 800;
  int height = 600;

  SdlWindow window {"Euphoria Demo", 800, 600};
  if (window.window == nullptr) {
    return -1;
  }

  SdlGlContext context {&window};

  if (context.context == nullptr) {
    return -1;
  }

  Init init;
  if (init.ok == false) {
    return -4;
  }

  SetupOpenglDebug();

  Viewport viewport { Recti::FromTopLeftWidthHeight(0,0, width, height) };
  viewport.Activate();

  FileSystem file_system;
  auto catalog = FileSystemRootCatalog::AddRoot(&file_system);
  FileSystemRootFolder::AddRoot(&file_system);
  catalog->RegisterFileString("default_shader.vert",
                              "#version 330 core\n"
                                  "in vec3 aPosition;\n"
                                  "in vec2 aTexCoord;\n"
                                  "\n"
                                  "out vec2 texCoord;\n"
                                  "\n"
                                  "uniform mat4 uProjection;\n"
                                  "uniform mat4 uView;\n"
                                  "uniform mat4 uModel;\n"
                                  "\n"
                                  "void main()\n"
                                  "{\n"
                                  "    gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);\n"
                                  "    texCoord = aTexCoord;\n"
                                  "}\n");
  catalog->RegisterFileString("default_shader.frag",
                              "#version 330 core\n"
                                  "out vec4 FragColor;\n"
                                  "\n"
                                  "in vec2 texCoord;\n"
                                  "\n"
                                  "uniform sampler2D uTexture;\n"
                                  "\n"
                                  "void main()\n"
                                  "{\n"
                                  "    FragColor = texture(uTexture, texCoord);\n"
                                  "}\n");

  MaterialShader shader;
  const bool shader_compile = shader.Load(&file_system, "default_shader");

  if(!shader_compile) {
    return -3;
  }

  auto texture_uniform = shader.shader_.GetUniform("uTexture");

  Image image;
  image.Setup(256, 256, false);
  Draw drawer{&image};
  const auto wi = drawer.WholeImage();
  drawer
      .Clear(Rgb::From(Color::Red));
  Random random {42};

  for(int i=0; i<20; i+= 1) {
    const auto color = Rgb::From(random.NextDawnbringerPalette());
    const auto pos = random.NextPoint(wi);
    const auto outer = random.NextRange(55.0f, 100.0f);
    const auto inner = random.NextRange(50.0f);
    drawer.Circle(color, pos, outer, 10, inner);
  }
  drawer
      .LineAntialiased(Rgb::From(Color::Black), wi.TopLeft(), wi.BottomRight())
      .LineAntialiased(Rgb::From(Color::Black), wi.BottomLeft(), wi.TopRight())
    .Text(wi.GetAbsoluteCenterPos(), "Hello world", Rgb::From(Color::Black), 2)
      ;
  catalog->RegisterFileData("image", image.Write(ImageWriteFormat::PNG));

  Texture2d texture;
  texture.LoadFromFile(&file_system, "image", AlphaLoad::Remove, Texture2dLoadData{});

  bool running = true;

  SdlTimer timer;

  World world;

  auto box = CompileMesh(meshes::CreateCube(0.5f));

  const float box_extent_value = 4;
  Aabb box_extents
    { vec3f{-box_extent_value, -box_extent_value, -box_extent_value},
      vec3f{box_extent_value, box_extent_value, box_extent_value} };

  std::vector<CubeAnimation> animation_handler;

  for(int i=0; i<20; ++i)
  {
    std::shared_ptr<Actor> actor = std::make_shared<Actor>(box);
    world.AddActor(actor);

    CubeAnimation anim;
    anim.actor = actor;
    anim.from = random.NextQuatf();
    anim.to = random.NextQuatf();
    anim.rotation_speed = random.NextRange(0.5f, 1.0f);
    anim.move_speed = random.NextRange(0.5f, 1.0f);
    anim.timer = random.NextFloat01();

    // generate a position not too close to the center
    vec3f position = vec3f::Origo();
    do {
      position = random.NextVec3(box_extents);
    } while(position.GetLength() < 1.4f);

    actor->SetPosition( position );
    actor->SetRotation( anim.from );

    animation_handler.push_back(anim);
  }

  Camera camera;
  camera.SetPosition(vec3f(0,0,3));

  while (running) {
    const float delta = timer.Update();

    for(auto& anim: animation_handler)
    {
      anim.timer += delta * anim.rotation_speed;
      int count = 0;
      while(anim.timer > 1.0f)
      {
        count += 1;
        anim.timer -= 1.0f;
        anim.from = anim.to;
        anim.to = random.NextQuatf();
        anim.rotation_speed = random.NextRange(0.3f, 1.0f);
        anim.move_speed = random.NextRange(0.2f, 3.0f);
      }
      Assert(count < 2);
      quatf q = quatf::SlerpShortway(anim.from, anim.timer, anim.to);
      anim.actor->SetRotation(q);
      const vec3f movement = q.In()*anim.move_speed*delta;
      const vec3f new_pos = box_extents.Wrap(anim.actor->GetPosition() + movement);
      anim.actor->SetPosition( new_pos );
    }

    SDL_Event e;
    while (SDL_PollEvent(&e) != 0) {
      switch (e.type) {
        case SDL_QUIT:
          running = false;
          break;
        case SDL_KEYDOWN:
        case SDL_KEYUP:
          {
            const bool down = e.type == SDL_KEYDOWN;
            switch( e.key.keysym.sym ) {
              case SDLK_ESCAPE:
                if(down) {
                  running = false;
                }
                break;
              default:
                // ignore other keys
                break;
            }
          }
          break;
        default:
          // ignore other events
          break;
      }
    }

    init.ClearScreen(Rgb::From(Color::DarkslateGray));
    shader.UseShader();
    BindTextureToShader(&texture, &shader.shader_, texture_uniform, 0);
    world.Render(viewport, camera, &shader);

    SDL_GL_SwapWindow(window.window);
  }

  return 0;
}

#if 0
class View {
Camera[] cameras;
};

class CameraView {
Camera;
ViewPort area; // glViewport
};

class Camera {
Mode mode;
World world;
culling info from world, created when camera is added to world
viewMatrix; // position + rotation
projectionMatrix; // ortho/perspective

// 4 planes from the projection matrix
getFrustum();

toViewSpace(); // camera space, eye space
toWorldSpace();
};

// normal, thermo optics/powerup
class Mode {
Pass[] passes;
};

class Pass {
tag/list
Shader shader;
};

class Shader {
material list: list of material names mapped to shader variables
};

class World {
Actor[] objects;
};

class Actor {
Mesh mesh;
position;
rotation;
modelMatrix;
ToLocalSpace();
ToWorldSpace();
};

class Mesh {
MeshPart[] meshParts;
};

class MeshPart {
Material material;
};

class MaterialList {
maps id, material name, shader variable
};

class Material {
Texture[] textures;
};
#endif
<|endoftext|>


<commit_before>#ifndef CXX_CONVERSIONS_HXX
# define CXX_CONVERSIONS_HXX

# include <libport/assert.hh>
# include <libport/symbol.hh>

# include <object/cxx-object.hh>
# include <object/float.hh>
# include <object/list.hh>
# include <object/string.hh>
# include <object/tag.hh>
# include <scheduler/tag.hh>

namespace object
{
  // Nothing to do for objects
  template <>
  class CxxConvert<libport::shared_ptr<Object, true> >
  {
  public:
    static rObject
    to(const rObject& o, unsigned)
    {
      return o;
    }

    static rObject
    from(rObject o)
    {
      if (!o)
        return void_class;
      return o;
    }
  };

  // Convert between Urbi types
  template <typename Urbi>
  struct CxxConvert<libport::shared_ptr<Urbi, true> >
  {
    typedef libport::shared_ptr<Urbi, true> T;

    static T
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Urbi::proto, idx);
      return o->as<Urbi>();
    }

    static rObject
    from(const T& v)
    {
      return v;
    }
  };

  // Convert between Urbi types pointers
  template <typename Urbi>
  struct CxxConvert<Urbi*>
  {
    static Urbi*
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Urbi::proto, idx);
      return o->as<Urbi>().get();
    }

    static rObject
    from(Urbi* v)
    {
      return v;
    }
  };

  // Conversion with int
  template<>
  struct CxxConvert<int>
  {
    static int
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Float::proto, idx);
      return o->as<Float>()->to_int();
    }

    static rObject
    from(const int& v)
    {
      return new Float(v);
    }
  };

  // Conversion with unsigned int
  template<>
  struct CxxConvert<unsigned int>
  {
    static unsigned int
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Float::proto, idx);
      return o->as<Float>()->to_unsigned_int();
    }

    static rObject
    from(const unsigned int& v)
    {
      return new Float(v);
    }
  };

  // Conversion with floating point
  template<>
  struct CxxConvert<Float::value_type>
  {
    static Float::value_type
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Float::proto, idx);
      return o->as<Float>()->value_get();
    }

    static rObject
    from(const Float::value_type& v)
    {
      return new Float(v);
    }
  };

  // Conversion with std::strings
  template <>
  struct CxxConvert<std::string>
  {
    static std::string
    to(const rObject& o, unsigned idx)
    {
      type_check(o, String::proto, idx);
      return o->as<String>()->value_get();
    }

    static rObject
    from(const std::string& v)
    {
      return new String(v);
    }
  };

  // Conversion with libport::Symbols
  template <>
  struct CxxConvert<libport::Symbol>
  {
    static libport::Symbol
    to(const rObject& o, unsigned idx)
    {
      type_check(o, String::proto, idx);
      return libport::Symbol(o->as<String>()->value_get());
    }

    static rObject
    from(const libport::Symbol& v)
    {
      return new String(v.name_get());
    }
  };

  // Conversion with bools
  template <>
  struct CxxConvert<bool>
  {
    static bool
    to(const rObject& o, unsigned)
    {
      return is_true(o);
    }

    static rObject
    from(bool v)
    {
      return v ? true_class : false_class;
    }
  };

  // Conversion with tags_type
  template <>
  struct CxxConvert<scheduler::tags_type>
  {
    static scheduler::tags_type
    to(const rObject&, unsigned)
    {
      pabort("Invalid conversion");
    }

    static rObject
    from(const scheduler::tags_type& v)
    {
      List::value_type res;
      foreach (const scheduler::rTag& tag, v)
	res.push_back(new Tag(tag));
      return new List(res);
    }
  };

  // Conversion with containers
#define CONTAINER(Name)                                                 \
  template <typename T>                                                 \
  struct CxxConvert<Name<T> >                                           \
  {                                                                     \
    static Name<T>                                                      \
      to(const rObject& o, unsigned idx)                                \
    {                                                                   \
      type_check(o, List::proto);                                       \
      Name<T> res;                                                      \
      foreach (const rObject& elt, o->as<List>()->value_get())          \
        res.insert(CxxConvert<T>::to(elt, idx));                        \
      return res;                                                       \
    }                                                                   \
                                                                        \
    static rObject                                                      \
      from(const Name<T>& v)                                            \
    {                                                                   \
      objects_type res;                                                 \
      foreach (const T& elt, v)                                         \
        res.push_back(CxxConvert<T>::from(elt));                        \
      return new List(res);                                             \
    }                                                                   \
  };                                                                    \

  CONTAINER(std::set);
  CONTAINER(std::vector);

#undef CONTAINER

  template <typename T>
  rObject to_urbi(const T& v)
  {
    return CxxConvert<T>::from(v);
  }
}

#endif
<commit_msg>Fix urbi conversions with std::vectors.<commit_after>#ifndef CXX_CONVERSIONS_HXX
# define CXX_CONVERSIONS_HXX

# include <libport/assert.hh>
# include <libport/symbol.hh>

# include <object/cxx-object.hh>
# include <object/float.hh>
# include <object/list.hh>
# include <object/string.hh>
# include <object/tag.hh>
# include <scheduler/tag.hh>

namespace object
{
  // Nothing to do for objects
  template <>
  class CxxConvert<libport::shared_ptr<Object, true> >
  {
  public:
    static rObject
    to(const rObject& o, unsigned)
    {
      return o;
    }

    static rObject
    from(rObject o)
    {
      if (!o)
        return void_class;
      return o;
    }
  };

  // Convert between Urbi types
  template <typename Urbi>
  struct CxxConvert<libport::shared_ptr<Urbi, true> >
  {
    typedef libport::shared_ptr<Urbi, true> T;

    static T
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Urbi::proto, idx);
      return o->as<Urbi>();
    }

    static rObject
    from(const T& v)
    {
      return v;
    }
  };

  // Convert between Urbi types pointers
  template <typename Urbi>
  struct CxxConvert<Urbi*>
  {
    static Urbi*
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Urbi::proto, idx);
      return o->as<Urbi>().get();
    }

    static rObject
    from(Urbi* v)
    {
      return v;
    }
  };

  // Conversion with int
  template<>
  struct CxxConvert<int>
  {
    static int
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Float::proto, idx);
      return o->as<Float>()->to_int();
    }

    static rObject
    from(const int& v)
    {
      return new Float(v);
    }
  };

  // Conversion with unsigned int
  template<>
  struct CxxConvert<unsigned int>
  {
    static unsigned int
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Float::proto, idx);
      return o->as<Float>()->to_unsigned_int();
    }

    static rObject
    from(const unsigned int& v)
    {
      return new Float(v);
    }
  };

  // Conversion with floating point
  template<>
  struct CxxConvert<Float::value_type>
  {
    static Float::value_type
    to(const rObject& o, unsigned idx)
    {
      type_check(o, Float::proto, idx);
      return o->as<Float>()->value_get();
    }

    static rObject
    from(const Float::value_type& v)
    {
      return new Float(v);
    }
  };

  // Conversion with std::strings
  template <>
  struct CxxConvert<std::string>
  {
    static std::string
    to(const rObject& o, unsigned idx)
    {
      type_check(o, String::proto, idx);
      return o->as<String>()->value_get();
    }

    static rObject
    from(const std::string& v)
    {
      return new String(v);
    }
  };

  // Conversion with libport::Symbols
  template <>
  struct CxxConvert<libport::Symbol>
  {
    static libport::Symbol
    to(const rObject& o, unsigned idx)
    {
      type_check(o, String::proto, idx);
      return libport::Symbol(o->as<String>()->value_get());
    }

    static rObject
    from(const libport::Symbol& v)
    {
      return new String(v.name_get());
    }
  };

  // Conversion with bools
  template <>
  struct CxxConvert<bool>
  {
    static bool
    to(const rObject& o, unsigned)
    {
      return is_true(o);
    }

    static rObject
    from(bool v)
    {
      return v ? true_class : false_class;
    }
  };

  // Conversion with tags_type
  template <>
  struct CxxConvert<scheduler::tags_type>
  {
    static scheduler::tags_type
    to(const rObject&, unsigned)
    {
      pabort("Invalid conversion");
    }

    static rObject
    from(const scheduler::tags_type& v)
    {
      List::value_type res;
      foreach (const scheduler::rTag& tag, v)
	res.push_back(new Tag(tag));
      return new List(res);
    }
  };

  // Conversion with containers
#define CONTAINER(Name, Method)                                         \
  template <typename T>                                                 \
  struct CxxConvert<Name<T> >                                           \
  {                                                                     \
    static Name<T>                                                      \
      to(const rObject& o, unsigned idx)                                \
    {                                                                   \
      type_check(o, List::proto);                                       \
      Name<T> res;                                                      \
      foreach (const rObject& elt, o->as<List>()->value_get())          \
        res.Method(CxxConvert<T>::to(elt, idx));                        \
      return res;                                                       \
    }                                                                   \
                                                                        \
    static rObject                                                      \
      from(const Name<T>& v)                                            \
    {                                                                   \
      objects_type res;                                                 \
      foreach (const T& elt, v)                                         \
        res.push_back(CxxConvert<T>::from(elt));                        \
      return new List(res);                                             \
    }                                                                   \
  };                                                                    \

  CONTAINER(std::set, insert);
  CONTAINER(std::vector, push_back);

#undef CONTAINER

  template <typename T>
  rObject to_urbi(const T& v)
  {
    return CxxConvert<T>::from(v);
  }
}

#endif
<|endoftext|>


<commit_before>/**
The MIT License (MIT)

Copyright (c) <2013> <Moritz Schulze>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
**/

#include "NodeSearch.h"
#include "NodeTrack.h"
#include "NodeAlbum.h"
#include "NodeArtist.h"
#include "NodePlaylist.h"
#include "../../events.h"
#include "../../Application.h"

extern Application* application;

NodeSearch::NodeSearch(const char* _searchQuery) : searchQuery(_searchQuery), trackOffset(0), albumOffset(0), artistOffset(0), playlistOffset(0),
  trackLimit(10), albumLimit(10), artistLimit(10), playlistLimit(10) {

}

NodeSearch::NodeSearch(const char* _searchQuery, int offset) : searchQuery(_searchQuery), trackOffset(offset), albumOffset(offset), artistOffset(offset), playlistOffset(offset),
  trackLimit(10), albumLimit(10), artistLimit(10), playlistLimit(10) {

}

NodeSearch::NodeSearch(const char* _searchQuery, int offset, int limit) : searchQuery(_searchQuery), trackOffset(offset), albumOffset(offset), artistOffset(offset), playlistOffset(offset),
  trackLimit(limit), albumLimit(limit), artistLimit(limit), playlistLimit(limit) {

}

Handle<Value> NodeSearch::execute(const Arguments& args) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(args.This());
  Persistent<Function> callback = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
  nodeSearch->on(SEARCH_COMPLETE, callback);
  nodeSearch->search = std::make_shared<Search>();
  nodeSearch->search->nodeObject = nodeSearch;
  nodeSearch->search->execute(nodeSearch->searchQuery, nodeSearch->trackOffset, nodeSearch->trackLimit,
    nodeSearch->albumOffset, nodeSearch->albumLimit,
    nodeSearch->artistOffset, nodeSearch->artistLimit,
    nodeSearch->playlistLimit, nodeSearch->playlistLimit);
  nodeSearch->setupAdditionalMethods();
  return scope.Close(Undefined());
}

/**
 * Adds adiitional properties to the V8 object.
 * These will call libspotify functions and should first be available when the search has been executed.
 **/
void NodeSearch::setupAdditionalMethods() {
  Handle<Object> nodeObject = this->getV8Object();
  nodeObject->SetAccessor(String::NewSymbol("didYouMean"), didYouMean);
  nodeObject->SetAccessor(String::NewSymbol("link"), getLink);
  nodeObject->SetAccessor(String::NewSymbol("tracks"), getTracks);
  nodeObject->SetAccessor(String::NewSymbol("albums"), getAlbums);
  nodeObject->SetAccessor(String::NewSymbol("artists"), getArtists);
  nodeObject->SetAccessor(String::NewSymbol("playlists"), getPlaylists);
  nodeObject->SetAccessor(String::NewSymbol("totalTracks"), getTotalTracks);
  nodeObject->SetAccessor(String::NewSymbol("totalAlbums"), getTotalAlbums);
  nodeObject->SetAccessor(String::NewSymbol("totalArtists"), getTotalArtists);
  nodeObject->SetAccessor(String::NewSymbol("totalPlaylists"), getTotalPlaylists);
}

Handle<Value> NodeSearch::getTrackOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->trackOffset));
}

void NodeSearch::setTrackOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->trackOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getAlbumOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->albumOffset));
}

void NodeSearch::setAlbumOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->albumOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getArtistOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->artistOffset));
}

void NodeSearch::setArtistOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->artistOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getPlaylistOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->playlistOffset));
}

void NodeSearch::setPlaylistOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->playlistOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getTrackLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->trackLimit));
}

void NodeSearch::setTrackLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->trackLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getAlbumLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->albumLimit));
}

void NodeSearch::setAlbumLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->albumLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getArtistLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->artistLimit));
}

void NodeSearch::setArtistLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->artistLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getPlaylistLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->playlistLimit));
}

void NodeSearch::setPlaylistLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->playlistLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::New(const Arguments& args) {
  HandleScope scope;
  NodeSearch* search;
  String::Utf8Value searchQuery(args[0]->ToString());
  if(args.Length() == 1) {
    search = new NodeSearch(*searchQuery);
  } else if(args.Length() == 2) {
    int offset = args[1]->ToInteger()->Value();
    search = new NodeSearch(*searchQuery, offset);
  } else if(args.Length() == 3) {
    int offset = args[1]->ToInteger()->Value();
    int limit = args[2]->ToInteger()->Value();
    search = new NodeSearch(*searchQuery, offset, limit);
  } else {
    return scope.Close(ThrowException(Exception::Error(String::New("Wrong arguments to search"))));
  }
  search->Wrap(args.This());
  return scope.Close(args.This());
}

Handle<Value> NodeSearch::didYouMean(Local<String> property, const AccessorInfo& info) {
    HandleScope scope;
    NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
    return scope.Close(String::New(nodeSearch->search->didYouMeanText().c_str()));
}

Handle<Value> NodeSearch::getLink(Local<String> property, const AccessorInfo& info) {
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return String::New(nodeSearch->search->link().c_str());
}

Handle<Value> NodeSearch::getTracks(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Track>> tracks = nodeSearch->search->getTracks();
  Local<Array> outArray = Array::New(tracks.size());
  for(int i = 0; i < (int)tracks.size(); i++) {
    NodeTrack* nodeTrack = new NodeTrack(tracks[i]);
    outArray->Set(Number::New(i), nodeTrack->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getAlbums(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Album>> albums = nodeSearch->search->getAlbums();
  Local<Array> outArray = Array::New(albums.size());
  for(int i = 0; i < (int)albums.size(); i++) {
    NodeAlbum* nodeAlbum = new NodeAlbum(albums[i]);
    outArray->Set(Number::New(i), nodeAlbum->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getArtists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Artist>> artists = nodeSearch->search->getArtists();
  Local<Array> outArray = Array::New(artists.size());
  for(int i = 0; i < (int)artists.size(); i++) {
    NodeArtist* nodeArtist = new NodeArtist(artists[i]);
    outArray->Set(Number::New(i), nodeArtist->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getPlaylists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Playlist>> playlists = nodeSearch->search->getPlaylists();
  Local<Array> outArray = Array::New(playlists.size());
  for(int i = 0; i < (int)playlists.size(); i++) {
    NodePlaylist* nodePlaylist = new NodePlaylist(playlists[i]);
    outArray->Set(Number::New(i), nodePlaylist->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getTotalTracks(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalTracks()));
}

Handle<Value> NodeSearch::getTotalAlbums(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalAlbums()));
}

Handle<Value> NodeSearch::getTotalArtists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalArtists()));
}

Handle<Value> NodeSearch::getTotalPlaylists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalPlaylists()));
}

Handle<Function> NodeSearch::getConstructor() {
  HandleScope scope;
  return scope.Close(constructor);
}

void NodeSearch::init() {
HandleScope scope;
  Local<FunctionTemplate> constructorTemplate = FunctionTemplate::New(New);
  constructorTemplate->SetClassName(String::NewSymbol("Search"));
  constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "execute", execute);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("trackOffset"), getTrackOffset, setTrackOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("trackLimit"), getTrackLimit, setTrackLimit);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("albumOffset"), getAlbumOffset, setAlbumOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("albumLimit"), getAlbumLimit, setAlbumLimit);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("artistOffset"), getArtistOffset, setArtistOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("artistLimit"), getArtistLimit, setArtistLimit);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("playlistOffset"), getPlaylistOffset, setPlaylistOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("playlistLimit"), getPlaylistLimit, setPlaylistLimit);
  constructor = Persistent<Function>::New(constructorTemplate->GetFunction());
  scope.Close(Undefined());
}<commit_msg>Added V8 Exception macro to NodeSearch<commit_after>/**
The MIT License (MIT)

Copyright (c) <2013> <Moritz Schulze>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
**/

#include "NodeSearch.h"
#include "NodeTrack.h"
#include "NodeAlbum.h"
#include "NodeArtist.h"
#include "NodePlaylist.h"
#include "../../events.h"
#include "../../Application.h"
#include "../../common_macros.h"

extern Application* application;

NodeSearch::NodeSearch(const char* _searchQuery) : searchQuery(_searchQuery), trackOffset(0), albumOffset(0), artistOffset(0), playlistOffset(0),
  trackLimit(10), albumLimit(10), artistLimit(10), playlistLimit(10) {

}

NodeSearch::NodeSearch(const char* _searchQuery, int offset) : searchQuery(_searchQuery), trackOffset(offset), albumOffset(offset), artistOffset(offset), playlistOffset(offset),
  trackLimit(10), albumLimit(10), artistLimit(10), playlistLimit(10) {

}

NodeSearch::NodeSearch(const char* _searchQuery, int offset, int limit) : searchQuery(_searchQuery), trackOffset(offset), albumOffset(offset), artistOffset(offset), playlistOffset(offset),
  trackLimit(limit), albumLimit(limit), artistLimit(limit), playlistLimit(limit) {

}

Handle<Value> NodeSearch::execute(const Arguments& args) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(args.This());
  Persistent<Function> callback = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
  nodeSearch->on(SEARCH_COMPLETE, callback);
  nodeSearch->search = std::make_shared<Search>();
  nodeSearch->search->nodeObject = nodeSearch;
  nodeSearch->search->execute(nodeSearch->searchQuery, nodeSearch->trackOffset, nodeSearch->trackLimit,
    nodeSearch->albumOffset, nodeSearch->albumLimit,
    nodeSearch->artistOffset, nodeSearch->artistLimit,
    nodeSearch->playlistLimit, nodeSearch->playlistLimit);
  nodeSearch->setupAdditionalMethods();
  return scope.Close(Undefined());
}

/**
 * Adds adiitional properties to the V8 object.
 * These will call libspotify functions and should first be available when the search has been executed.
 **/
void NodeSearch::setupAdditionalMethods() {
  Handle<Object> nodeObject = this->getV8Object();
  nodeObject->SetAccessor(String::NewSymbol("didYouMean"), didYouMean);
  nodeObject->SetAccessor(String::NewSymbol("link"), getLink);
  nodeObject->SetAccessor(String::NewSymbol("tracks"), getTracks);
  nodeObject->SetAccessor(String::NewSymbol("albums"), getAlbums);
  nodeObject->SetAccessor(String::NewSymbol("artists"), getArtists);
  nodeObject->SetAccessor(String::NewSymbol("playlists"), getPlaylists);
  nodeObject->SetAccessor(String::NewSymbol("totalTracks"), getTotalTracks);
  nodeObject->SetAccessor(String::NewSymbol("totalAlbums"), getTotalAlbums);
  nodeObject->SetAccessor(String::NewSymbol("totalArtists"), getTotalArtists);
  nodeObject->SetAccessor(String::NewSymbol("totalPlaylists"), getTotalPlaylists);
}

Handle<Value> NodeSearch::getTrackOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->trackOffset));
}

void NodeSearch::setTrackOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->trackOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getAlbumOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->albumOffset));
}

void NodeSearch::setAlbumOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->albumOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getArtistOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->artistOffset));
}

void NodeSearch::setArtistOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->artistOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getPlaylistOffset(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->playlistOffset));
}

void NodeSearch::setPlaylistOffset(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->playlistOffset = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getTrackLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->trackLimit));
}

void NodeSearch::setTrackLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->trackLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getAlbumLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->albumLimit));
}

void NodeSearch::setAlbumLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->albumLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getArtistLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->artistLimit));
}

void NodeSearch::setArtistLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->artistLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::getPlaylistLimit(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->playlistLimit));
}

void NodeSearch::setPlaylistLimit(Local<String> property, Local<Value> value, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  nodeSearch->playlistLimit = value->ToInteger()->Value();
  scope.Close(Undefined());
}

Handle<Value> NodeSearch::New(const Arguments& args) {
  HandleScope scope;
  NodeSearch* search;
  String::Utf8Value searchQuery(args[0]->ToString());
  if(args.Length() == 1) {
    search = new NodeSearch(*searchQuery);
  } else if(args.Length() == 2) {
    int offset = args[1]->ToInteger()->Value();
    search = new NodeSearch(*searchQuery, offset);
  } else if(args.Length() == 3) {
    int offset = args[1]->ToInteger()->Value();
    int limit = args[2]->ToInteger()->Value();
    search = new NodeSearch(*searchQuery, offset, limit);
  } else {
    return scope.Close(V8_EXCEPTION("Please provide an object to the node-spotify initializer function"));
  }
  search->Wrap(args.This());
  return scope.Close(args.This());
}

Handle<Value> NodeSearch::didYouMean(Local<String> property, const AccessorInfo& info) {
    HandleScope scope;
    NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
    return scope.Close(String::New(nodeSearch->search->didYouMeanText().c_str()));
}

Handle<Value> NodeSearch::getLink(Local<String> property, const AccessorInfo& info) {
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return String::New(nodeSearch->search->link().c_str());
}

Handle<Value> NodeSearch::getTracks(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Track>> tracks = nodeSearch->search->getTracks();
  Local<Array> outArray = Array::New(tracks.size());
  for(int i = 0; i < (int)tracks.size(); i++) {
    NodeTrack* nodeTrack = new NodeTrack(tracks[i]);
    outArray->Set(Number::New(i), nodeTrack->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getAlbums(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Album>> albums = nodeSearch->search->getAlbums();
  Local<Array> outArray = Array::New(albums.size());
  for(int i = 0; i < (int)albums.size(); i++) {
    NodeAlbum* nodeAlbum = new NodeAlbum(albums[i]);
    outArray->Set(Number::New(i), nodeAlbum->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getArtists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Artist>> artists = nodeSearch->search->getArtists();
  Local<Array> outArray = Array::New(artists.size());
  for(int i = 0; i < (int)artists.size(); i++) {
    NodeArtist* nodeArtist = new NodeArtist(artists[i]);
    outArray->Set(Number::New(i), nodeArtist->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getPlaylists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  std::vector<std::shared_ptr<Playlist>> playlists = nodeSearch->search->getPlaylists();
  Local<Array> outArray = Array::New(playlists.size());
  for(int i = 0; i < (int)playlists.size(); i++) {
    NodePlaylist* nodePlaylist = new NodePlaylist(playlists[i]);
    outArray->Set(Number::New(i), nodePlaylist->getV8Object());
  }
  return scope.Close(outArray);
}

Handle<Value> NodeSearch::getTotalTracks(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalTracks()));
}

Handle<Value> NodeSearch::getTotalAlbums(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalAlbums()));
}

Handle<Value> NodeSearch::getTotalArtists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalArtists()));
}

Handle<Value> NodeSearch::getTotalPlaylists(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSearch* nodeSearch = node::ObjectWrap::Unwrap<NodeSearch>(info.Holder());
  return scope.Close(Integer::New(nodeSearch->search->totalPlaylists()));
}

Handle<Function> NodeSearch::getConstructor() {
  HandleScope scope;
  return scope.Close(constructor);
}

void NodeSearch::init() {
HandleScope scope;
  Local<FunctionTemplate> constructorTemplate = FunctionTemplate::New(New);
  constructorTemplate->SetClassName(String::NewSymbol("Search"));
  constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "execute", execute);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("trackOffset"), getTrackOffset, setTrackOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("trackLimit"), getTrackLimit, setTrackLimit);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("albumOffset"), getAlbumOffset, setAlbumOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("albumLimit"), getAlbumLimit, setAlbumLimit);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("artistOffset"), getArtistOffset, setArtistOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("artistLimit"), getArtistLimit, setArtistLimit);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("playlistOffset"), getPlaylistOffset, setPlaylistOffset);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("playlistLimit"), getPlaylistLimit, setPlaylistLimit);
  constructor = Persistent<Function>::New(constructorTemplate->GetFunction());
  scope.Close(Undefined());
}<|endoftext|>


<commit_before>/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    smt2scanner.cpp

Abstract:

    <abstract>

Author:

    Leonardo de Moura (leonardo) 2011-03-09.

Revision History:

--*/
#include"smt2scanner.h"
#include"parser_params.hpp"

namespace smt2 {

    void scanner::next() {
        if (m_cache_input)
            m_cache.push_back(m_curr);
        SASSERT(m_curr != EOF);
        if (m_interactive) {
            m_curr = m_stream.get();
        }
        else if (m_bpos < m_bend) {
            m_curr = m_buffer[m_bpos];
            m_bpos++;
        }
        else {
            m_stream.read(m_buffer, SCANNER_BUFFER_SIZE);
            m_bend = static_cast<unsigned>(m_stream.gcount());
            m_bpos = 0;
            if (m_bpos == m_bend) {
                m_curr = EOF;
            }
            else {
                m_curr = m_buffer[m_bpos];
                m_bpos++;
            }
        }
        m_spos++;
    }

    void scanner::read_comment() {
        SASSERT(curr() == ';');
        next();
        while (true) {
            char c = curr();
            if (c == EOF)
                return;
            if (c == '\n') {
                new_line();
                next();
                return;
            }
            next();
        }
    }

    scanner::token scanner::read_quoted_symbol() {
        SASSERT(curr() == '|');
        bool escape = false;
        m_string.reset();
        next();
        while (true) {
            char c = curr();
            if (c == EOF) {
                throw scanner_exception("unexpected end of quoted symbol", m_line, m_spos);
            }
            else if (c == '\n') {
                new_line();
            }
            else if (c == '|' && !escape) {
                next();
                m_string.push_back(0);
                m_id = m_string.begin();
                TRACE("scanner", tout << "new quoted symbol: " << m_id << "\n";);
                return SYMBOL_TOKEN;
            }
            escape = (c == '\\');
            m_string.push_back(c);
            next();
        }
    }

    scanner::token scanner::read_symbol_core() {
        while (true) {
            char c = curr();
            signed char n = m_normalized[static_cast<unsigned char>(c)];
            if (n == 'a' || n == '0' || n == '-') {
                m_string.push_back(c);
                next();
            }
            else {
                m_string.push_back(0);
                m_id = m_string.begin();
                TRACE("scanner", tout << "new symbol: " << m_id << "\n";);
                return SYMBOL_TOKEN;
            }
        }
    }

    scanner::token scanner::read_symbol() {
        SASSERT(m_normalized[static_cast<unsigned>(curr())] == 'a' || curr() == ':' || curr() == '-');
        m_string.reset();
        m_string.push_back(curr());
        next();
        return read_symbol_core();
    }

    scanner::token scanner::read_number() {
        SASSERT('0' <= curr() && curr() <= '9');
        rational q(1);
        m_number = rational(curr() - '0');
        next();
        bool is_float = false;

        while (true) {
            char c = curr();
            if ('0' <= c && c <= '9') {
                m_number = rational(10)*m_number + rational(c - '0');
                if (is_float)
                    q *= rational(10);
                next();
            }
            else if (c == '.') {
                if (is_float)
                    break;
                is_float = true;
                next();
            }
            else {
                break;
            }
        }
        if (is_float)
            m_number /= q;
        TRACE("scanner", tout << "new number: " << m_number << "\n";);
        return is_float ? FLOAT_TOKEN : INT_TOKEN;
    }

    scanner::token scanner::read_signed_number() {
        SASSERT(curr() == '-');
        next();
        if ('0' <= curr() && curr() <= '9') {
            scanner::token r = read_number();
            m_number.neg();
            return r;
        }
        else {
            // it is a symbol.
            m_string.reset();
            m_string.push_back('-');
            return read_symbol_core();
        }
    }

    scanner::token scanner::read_string() {
        SASSERT(curr() == '\"');
        next();
        m_string.reset();
        while (true) {
            char c = curr();
            if (c == EOF)
                throw scanner_exception("unexpected end of string", m_line, m_spos);
            if (c == '\"') {
                next();
                m_string.push_back(0);
                return STRING_TOKEN;
            }
            if (c == '\n')
                new_line();
            else if (c == '\\') {
                next();
                c = curr();
                if (c == EOF)
                    throw scanner_exception("unexpected end of string", m_line, m_spos);
                if (c != '\\' && c != '\"')
                    throw scanner_exception("invalid escape sequence", m_line, m_spos);
            }
            m_string.push_back(c);
            next();
        }
    }

    scanner::token scanner::read_bv_literal() {
        SASSERT(curr() == '#');
        next();
        char c = curr();
        if (c == 'x') {
            next();
            c = curr();
            m_number  = rational(0);
            m_bv_size = 0;
            while (true) {
                if ('0' <= c && c <= '9') {
                    m_number *= rational(16);
                    m_number += rational(c - '0');
                }
                else if ('a' <= c && c <= 'f') {
                    m_number *= rational(16);
                    m_number += rational(10 + (c - 'a'));
                }
                else if ('A' <= c && c <= 'F') {
                    m_number *= rational(16);
                    m_number += rational(10 + (c - 'A'));
                }
                else {
                    if (m_bv_size == 0)
                        throw scanner_exception("invalid empty bit-vector literal", m_line, m_spos);
                    return BV_TOKEN;
                }
                m_bv_size += 4;
                next();
                c = curr();
            }
        }
        else if (c == 'b') {
            next();
            c = curr();
            m_number  = rational(0);
            m_bv_size = 0;
            while (c == '0' || c == '1') {
                m_number *= rational(2);
                m_number += rational(c - '0');
                m_bv_size++;
                next();
                c = curr();
            }
            if (m_bv_size == 0)
                throw scanner_exception("invalid empty bit-vector literal", m_line, m_spos);
            return BV_TOKEN;
        }
        else {
            throw scanner_exception("invalid bit-vector literal, expecting 'x' or 'b'", m_line, m_spos);
        }
    }

    scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive):
        m_interactive(interactive),
        m_spos(0),
        m_curr(0), // avoid Valgrind warning
        m_line(1),
        m_pos(0),
        m_bv_size(UINT_MAX),
        m_bpos(0),
        m_bend(0),
        m_stream(stream),
        m_cache_input(false) {

        m_smtlib2_compliant = ctx.params().m_smtlib2_compliant;

        for (int i = 0; i < 256; ++i) {
            m_normalized[i] = (signed char) i;
        }
        m_normalized[static_cast<int>('\t')] = ' ';
        m_normalized[static_cast<int>('\r')] = ' ';
        // assert ('a' < 'z');
        for (char ch = 'b'; ch <= 'z'; ++ch) {
            m_normalized[static_cast<int>(ch)] = 'a';
        }
        for (char ch = 'A'; ch <= 'Z'; ++ch) {
            m_normalized[static_cast<int>(ch)] = 'a';
        }
        // assert ('0' < '9', '9' - '0' == 9);
        for (char ch = '1'; ch <= '9'; ++ch) {
            m_normalized[static_cast<int>(ch)] = '0';
        }
        // SMT2 "Symbols": ~ ! @ $ % ^ & * _ - + = < > . ? /
        m_normalized[static_cast<int>('~')] = 'a';
        m_normalized[static_cast<int>('!')] = 'a';
        m_normalized[static_cast<int>('@')] = 'a';
        m_normalized[static_cast<int>('$')] = 'a';
        m_normalized[static_cast<int>('%')] = 'a';
        m_normalized[static_cast<int>('^')] = 'a';
        m_normalized[static_cast<int>('&')] = 'a';
        m_normalized[static_cast<int>('*')] = 'a';
        m_normalized[static_cast<int>('_')] = 'a';
        m_normalized[static_cast<int>('-')] = '-';
        m_normalized[static_cast<int>('+')] = 'a';
        m_normalized[static_cast<int>('=')] = 'a';
        m_normalized[static_cast<int>('<')] = 'a';
        m_normalized[static_cast<int>('>')] = 'a';
        m_normalized[static_cast<int>('.')] = 'a';
        m_normalized[static_cast<int>('?')] = 'a';
        m_normalized[static_cast<int>('/')] = 'a';
        next();
    }

    scanner::token scanner::scan() {
        while (true) {
            signed char c = curr();
            m_pos = m_spos;
            switch (m_normalized[(unsigned char) c]) {
            case ' ':
                next();
                break;
            case '\n':
                next();
                new_line();
                break;
            case ';':
                read_comment();
                break;
            case ':':
                read_symbol();
                return KEYWORD_TOKEN;
            case '(':
                next();
                return LEFT_PAREN;
            case ')':
                next();
                return RIGHT_PAREN;
            case '|':
                return read_quoted_symbol();
            case 'a':
                return read_symbol();
            case '"':
                return read_string();
            case '0':
                return read_number();
            case '#':
                return read_bv_literal();
            case '-':
                if (m_smtlib2_compliant)
                    return read_symbol();
                else
                    return read_signed_number();
            case -1:
                return EOF_TOKEN;
            default: {
                scanner_exception ex("unexpected character", m_line, m_spos);
                next();
                throw ex;
            }}
        }
    }

    char const * scanner::cached_str(unsigned begin, unsigned end) {
        m_cache_result.reset();
        while (isspace(m_cache[begin]) && begin < end)
            begin++;
        while (begin < end && isspace(m_cache[end-1]))
            end--;
        for (unsigned i = begin; i < end; i++)
            m_cache_result.push_back(m_cache[i]);
        m_cache_result.push_back(0);
        return m_cache_result.begin();
    }

};

<commit_msg>parsing of SMT 2.5 style string literals<commit_after>/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    smt2scanner.cpp

Abstract:

    <abstract>

Author:

    Leonardo de Moura (leonardo) 2011-03-09.

Revision History:

--*/
#include"smt2scanner.h"
#include"parser_params.hpp"

namespace smt2 {

    void scanner::next() {
        if (m_cache_input)
            m_cache.push_back(m_curr);
        SASSERT(m_curr != EOF);
        if (m_interactive) {
            m_curr = m_stream.get();
        }
        else if (m_bpos < m_bend) {
            m_curr = m_buffer[m_bpos];
            m_bpos++;
        }
        else {
            m_stream.read(m_buffer, SCANNER_BUFFER_SIZE);
            m_bend = static_cast<unsigned>(m_stream.gcount());
            m_bpos = 0;
            if (m_bpos == m_bend) {
                m_curr = EOF;
            }
            else {
                m_curr = m_buffer[m_bpos];
                m_bpos++;
            }
        }
        m_spos++;
    }

    void scanner::read_comment() {
        SASSERT(curr() == ';');
        next();
        while (true) {
            char c = curr();
            if (c == EOF)
                return;
            if (c == '\n') {
                new_line();
                next();
                return;
            }
            next();
        }
    }

    scanner::token scanner::read_quoted_symbol() {
        SASSERT(curr() == '|');
        bool escape = false;
        m_string.reset();
        next();
        while (true) {
            char c = curr();
            if (c == EOF) {
                throw scanner_exception("unexpected end of quoted symbol", m_line, m_spos);
            }
            else if (c == '\n') {
                new_line();
            }
            else if (c == '|' && !escape) {
                next();
                m_string.push_back(0);
                m_id = m_string.begin();
                TRACE("scanner", tout << "new quoted symbol: " << m_id << "\n";);
                return SYMBOL_TOKEN;
            }
            escape = (c == '\\');
            m_string.push_back(c);
            next();
        }
    }

    scanner::token scanner::read_symbol_core() {
        while (true) {
            char c = curr();
            signed char n = m_normalized[static_cast<unsigned char>(c)];
            if (n == 'a' || n == '0' || n == '-') {
                m_string.push_back(c);
                next();
            }
            else {
                m_string.push_back(0);
                m_id = m_string.begin();
                TRACE("scanner", tout << "new symbol: " << m_id << "\n";);
                return SYMBOL_TOKEN;
            }
        }
    }

    scanner::token scanner::read_symbol() {
        SASSERT(m_normalized[static_cast<unsigned>(curr())] == 'a' || curr() == ':' || curr() == '-');
        m_string.reset();
        m_string.push_back(curr());
        next();
        return read_symbol_core();
    }

    scanner::token scanner::read_number() {
        SASSERT('0' <= curr() && curr() <= '9');
        rational q(1);
        m_number = rational(curr() - '0');
        next();
        bool is_float = false;

        while (true) {
            char c = curr();
            if ('0' <= c && c <= '9') {
                m_number = rational(10)*m_number + rational(c - '0');
                if (is_float)
                    q *= rational(10);
                next();
            }
            else if (c == '.') {
                if (is_float)
                    break;
                is_float = true;
                next();
            }
            else {
                break;
            }
        }
        if (is_float)
            m_number /= q;
        TRACE("scanner", tout << "new number: " << m_number << "\n";);
        return is_float ? FLOAT_TOKEN : INT_TOKEN;
    }

    scanner::token scanner::read_signed_number() {
        SASSERT(curr() == '-');
        next();
        if ('0' <= curr() && curr() <= '9') {
            scanner::token r = read_number();
            m_number.neg();
            return r;
        }
        else {
            // it is a symbol.
            m_string.reset();
            m_string.push_back('-');
            return read_symbol_core();
        }
    }

    scanner::token scanner::read_string() {
        SASSERT(curr() == '\"');
        next();
        m_string.reset();
        while (true) {
            char c = curr();
            if (c == EOF)
                throw scanner_exception("unexpected end of string", m_line, m_spos);
            if (c == '\"') {
                next();
                if (curr() == '\"') {
                    m_string.push_back(c);
                }
                else {
                    m_string.push_back(0);
                    return STRING_TOKEN;
                }
            }
            else if (c == '\n') {
                new_line();
            }
            else if (c == '\\') {
                next();
                c = curr();
                if (c == EOF)
                    throw scanner_exception("unexpected end of string", m_line, m_spos);
                if (c != '\\' && c != '\"')
                    throw scanner_exception("invalid escape sequence", m_line, m_spos);
            }
            m_string.push_back(c);
            next();
        }
    }

    scanner::token scanner::read_bv_literal() {
        SASSERT(curr() == '#');
        next();
        char c = curr();
        if (c == 'x') {
            next();
            c = curr();
            m_number  = rational(0);
            m_bv_size = 0;
            while (true) {
                if ('0' <= c && c <= '9') {
                    m_number *= rational(16);
                    m_number += rational(c - '0');
                }
                else if ('a' <= c && c <= 'f') {
                    m_number *= rational(16);
                    m_number += rational(10 + (c - 'a'));
                }
                else if ('A' <= c && c <= 'F') {
                    m_number *= rational(16);
                    m_number += rational(10 + (c - 'A'));
                }
                else {
                    if (m_bv_size == 0)
                        throw scanner_exception("invalid empty bit-vector literal", m_line, m_spos);
                    return BV_TOKEN;
                }
                m_bv_size += 4;
                next();
                c = curr();
            }
        }
        else if (c == 'b') {
            next();
            c = curr();
            m_number  = rational(0);
            m_bv_size = 0;
            while (c == '0' || c == '1') {
                m_number *= rational(2);
                m_number += rational(c - '0');
                m_bv_size++;
                next();
                c = curr();
            }
            if (m_bv_size == 0)
                throw scanner_exception("invalid empty bit-vector literal", m_line, m_spos);
            return BV_TOKEN;
        }
        else {
            throw scanner_exception("invalid bit-vector literal, expecting 'x' or 'b'", m_line, m_spos);
        }
    }

    scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive):
        m_interactive(interactive),
        m_spos(0),
        m_curr(0), // avoid Valgrind warning
        m_line(1),
        m_pos(0),
        m_bv_size(UINT_MAX),
        m_bpos(0),
        m_bend(0),
        m_stream(stream),
        m_cache_input(false) {

        m_smtlib2_compliant = ctx.params().m_smtlib2_compliant;

        for (int i = 0; i < 256; ++i) {
            m_normalized[i] = (signed char) i;
        }
        m_normalized[static_cast<int>('\t')] = ' ';
        m_normalized[static_cast<int>('\r')] = ' ';
        // assert ('a' < 'z');
        for (char ch = 'b'; ch <= 'z'; ++ch) {
            m_normalized[static_cast<int>(ch)] = 'a';
        }
        for (char ch = 'A'; ch <= 'Z'; ++ch) {
            m_normalized[static_cast<int>(ch)] = 'a';
        }
        // assert ('0' < '9', '9' - '0' == 9);
        for (char ch = '1'; ch <= '9'; ++ch) {
            m_normalized[static_cast<int>(ch)] = '0';
        }
        // SMT2 "Symbols": ~ ! @ $ % ^ & * _ - + = < > . ? /
        m_normalized[static_cast<int>('~')] = 'a';
        m_normalized[static_cast<int>('!')] = 'a';
        m_normalized[static_cast<int>('@')] = 'a';
        m_normalized[static_cast<int>('$')] = 'a';
        m_normalized[static_cast<int>('%')] = 'a';
        m_normalized[static_cast<int>('^')] = 'a';
        m_normalized[static_cast<int>('&')] = 'a';
        m_normalized[static_cast<int>('*')] = 'a';
        m_normalized[static_cast<int>('_')] = 'a';
        m_normalized[static_cast<int>('-')] = '-';
        m_normalized[static_cast<int>('+')] = 'a';
        m_normalized[static_cast<int>('=')] = 'a';
        m_normalized[static_cast<int>('<')] = 'a';
        m_normalized[static_cast<int>('>')] = 'a';
        m_normalized[static_cast<int>('.')] = 'a';
        m_normalized[static_cast<int>('?')] = 'a';
        m_normalized[static_cast<int>('/')] = 'a';
        next();
    }

    scanner::token scanner::scan() {
        while (true) {
            signed char c = curr();
            m_pos = m_spos;
            switch (m_normalized[(unsigned char) c]) {
            case ' ':
                next();
                break;
            case '\n':
                next();
                new_line();
                break;
            case ';':
                read_comment();
                break;
            case ':':
                read_symbol();
                return KEYWORD_TOKEN;
            case '(':
                next();
                return LEFT_PAREN;
            case ')':
                next();
                return RIGHT_PAREN;
            case '|':
                return read_quoted_symbol();
            case 'a':
                return read_symbol();
            case '"':
                return read_string();
            case '0':
                return read_number();
            case '#':
                return read_bv_literal();
            case '-':
                if (m_smtlib2_compliant)
                    return read_symbol();
                else
                    return read_signed_number();
            case -1:
                return EOF_TOKEN;
            default: {
                scanner_exception ex("unexpected character", m_line, m_spos);
                next();
                throw ex;
            }}
        }
    }

    char const * scanner::cached_str(unsigned begin, unsigned end) {
        m_cache_result.reset();
        while (isspace(m_cache[begin]) && begin < end)
            begin++;
        while (begin < end && isspace(m_cache[end-1]))
            end--;
        for (unsigned i = begin; i < end; i++)
            m_cache_result.push_back(m_cache[i]);
        m_cache_result.push_back(0);
        return m_cache_result.begin();
    }

};

<|endoftext|>


<commit_before>#include <communication.h>

Communication::Communication(ObjectExtractor *p_obj_e, FileAPI *p_api, JacoCustom *p_jaco)
{
    m_object_ex_ptr = p_obj_e;
    m_api_ptr = p_api;
    m_jaco_ptr = p_jaco;
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = false;
}

//-----------------------------------------------------------------------------------//
void Communication::callback_android_listener(const std_msgs::String &p_input)
{

    switch(p_input.data[0])
    {
    case('c'):coordinate_processing(p_input);break;
    case('t'):train_processing(p_input);break;
    case('g'):grasp_processing(p_input);break;
    default:break;
    }
}

//---------------------------------------------------------------------------------//
void Communication::coordinate_processing(std_msgs::String p_coordinate)
{
    m_coordinate_received = true;
    m_grasp_received = false;
    m_train_received = false;

    std::string string_temp = "";
    for(int i = 0; i < p_coordinate.data.size(); i ++)
    {
        if(p_coordinate.data.at(i) == '_')
        {
            m_coordinate_user_sended[0] = atof(string_temp.c_str());
            string_temp.clear();
        }
        else
            string_temp += p_coordinate.data.at(i);

    }
    m_coordinate_user_sended[1] = atof(string_temp.c_str());
    m_coordinate_user_sended[0] = m_coordinate_user_sended[0]*640;
    m_coordinate_user_sended[1] = m_coordinate_user_sended[1]*480;
}

//----------------------------------------------------------------------------------------//
void Communication::grasp_processing(std_msgs::String p_grasp)
{
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = true;
}

//------------------------------------------------------------------------------------------//
void Communication::train_processing(std_msgs::String p_train)
{
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = true;
}

//------------------------------------------------------------------------------------------//
bool Communication::get_coordinate_received() const
{
    return m_coordinate_received;
}

//--------------------------------------------------------------------------------------------//
bool Communication::get_grasp_received() const
{
    return m_grasp_received;
}

//---------------------------------------------------------------------------------------------//
bool Communication::get_train_received() const
{
    return m_train_received;
}

//-----------------------------------------------------------------------------------------------//
void Communication::spin_once()
{
    if(m_coordinate_received)
    {
<<<<<<< HEAD
        m_position_vector_cvfh = m_object_ex_ptr->coordinate_processing(m_coordinate_user_sended,
                                                                        m_api_ptr->getAllHistograme());
=======
        m_object_ex_ptr->coordinate_processing(m_coordinate_user_sended,m_api_ptr->getAllHistograme());
>>>>>>> 16b3b8e014bb70d8fa93a2d0e776351da282e0ac
        m_object_ex_ptr->spin_once();

        //pour retrouver l'object qui est reconnue par le cvfh
        //m_api_ptr->retrieveObjectFromHistogramme(m_position_vector_cvfh);
    }
    else if(m_train_received)
    {
        train();
    }
    else if(m_grasp_received)
    {

    }
    else
    {
        m_object_ex_ptr->spin_once();
    }
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = false;
}

//-----------------------------------------------------------------------------------------------//
void Communication::train(){
    //
    Object obj;
    //obj.name = m_api_ptr->findDefaultName();
    //obj.object_pointcloud = m_object_ex_ptr->getObjectToGrasp();

    // OBJECT POSE
    //obj.object_pose = ; // find object pose
    tf::StampedTransform object_tf = m_object_ex_ptr->getCentroidPositionRGBFrame();

    // JACO POSE
    // tf::StampedTransform arm_pose_before_grasp = m_jaco_ptr->getGraspArmPosition();
    // For testing purposes only, comment the following line and uncomment previous one
    tf::StampedTransform arm_pose_before_grasp = m_jaco_ptr->getArmPositionFromCamera();

    // RELATIVE POSE
    tf::Transform diff;
    tf::Vector3 translation = arm_pose_before_grasp.getOrigin() - object_tf.getOrigin();
    diff = tf::Transform(object_tf.getBasis().transposeTimes(arm_pose_before_grasp.getBasis()), translation);

    // TO VIEW FRAMES
    //static tf::TransformBroadcaster br;
    //br.sendTransform(object_tf);
    //br.sendTransform(tf::StampedTransform(diff,ros::Time::now(),"detected_object_centroids","jaco_relative_pose"));

    // PRINT POSE
    //    cout << "arm pose : [" <<   arm_pose_before_grasp.getOrigin().getX() << ", " <<
    //            arm_pose_before_grasp.getOrigin().getY() << ", " <<
    //            arm_pose_before_grasp.getOrigin().getZ() << "]" << endl;

}

void Communication::repeat(){

}

<commit_msg>Update communication.cpp<commit_after>#include <communication.h>

Communication::Communication(ObjectExtractor *p_obj_e, FileAPI *p_api, JacoCustom *p_jaco)
{
    m_object_ex_ptr = p_obj_e;
    m_api_ptr = p_api;
    m_jaco_ptr = p_jaco;
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = false;
}

//-----------------------------------------------------------------------------------//
void Communication::callback_android_listener(const std_msgs::String &p_input)
{

    switch(p_input.data[0])
    {
    case('c'):coordinate_processing(p_input);break;
    case('t'):train_processing(p_input);break;
    case('g'):grasp_processing(p_input);break;
    default:break;
    }
}

//---------------------------------------------------------------------------------//
void Communication::coordinate_processing(std_msgs::String p_coordinate)
{
    m_coordinate_received = true;
    m_grasp_received = false;
    m_train_received = false;

    std::string string_temp = "";
    for(int i = 0; i < p_coordinate.data.size(); i ++)
    {
        if(p_coordinate.data.at(i) == '_')
        {
            m_coordinate_user_sended[0] = atof(string_temp.c_str());
            string_temp.clear();
        }
        else
            string_temp += p_coordinate.data.at(i);

    }
    m_coordinate_user_sended[1] = atof(string_temp.c_str());
    m_coordinate_user_sended[0] = m_coordinate_user_sended[0]*640;
    m_coordinate_user_sended[1] = m_coordinate_user_sended[1]*480;
}

//----------------------------------------------------------------------------------------//
void Communication::grasp_processing(std_msgs::String p_grasp)
{
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = true;
}

//------------------------------------------------------------------------------------------//
void Communication::train_processing(std_msgs::String p_train)
{
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = true;
}

//------------------------------------------------------------------------------------------//
bool Communication::get_coordinate_received() const
{
    return m_coordinate_received;
}

//--------------------------------------------------------------------------------------------//
bool Communication::get_grasp_received() const
{
    return m_grasp_received;
}

//---------------------------------------------------------------------------------------------//
bool Communication::get_train_received() const
{
    return m_train_received;
}

//-----------------------------------------------------------------------------------------------//
void Communication::spin_once()
{
    if(m_coordinate_received)
    {
        m_position_vector_cvfh = m_object_ex_ptr->coordinate_processing(m_coordinate_user_sended,
                                                                        m_api_ptr->getAllHistograme());

        m_object_ex_ptr->coordinate_processing(m_coordinate_user_sended,m_api_ptr->getAllHistograme());
        m_object_ex_ptr->spin_once();

        //pour retrouver l'object qui est reconnue par le cvfh
        //m_api_ptr->retrieveObjectFromHistogramme(m_position_vector_cvfh);
    }
    else if(m_train_received)
    {
        train();
    }
    else if(m_grasp_received)
    {

    }
    else
    {
        m_object_ex_ptr->spin_once();
    }
    m_coordinate_received = false;
    m_grasp_received = false;
    m_train_received = false;
}

//-----------------------------------------------------------------------------------------------//
void Communication::train(){
    //
    Object obj;
    //obj.name = m_api_ptr->findDefaultName();
    //obj.object_pointcloud = m_object_ex_ptr->getObjectToGrasp();

    // OBJECT POSE
    //obj.object_pose = ; // find object pose
    tf::StampedTransform object_tf = m_object_ex_ptr->getCentroidPositionRGBFrame();

    // JACO POSE
    // tf::StampedTransform arm_pose_before_grasp = m_jaco_ptr->getGraspArmPosition();
    // For testing purposes only, comment the following line and uncomment previous one
    tf::StampedTransform arm_pose_before_grasp = m_jaco_ptr->getArmPositionFromCamera();

    // RELATIVE POSE
    tf::Transform diff;
    tf::Vector3 translation = arm_pose_before_grasp.getOrigin() - object_tf.getOrigin();
    diff = tf::Transform(object_tf.getBasis().transposeTimes(arm_pose_before_grasp.getBasis()), translation);

    // TO VIEW FRAMES
    //static tf::TransformBroadcaster br;
    //br.sendTransform(object_tf);
    //br.sendTransform(tf::StampedTransform(diff,ros::Time::now(),"detected_object_centroids","jaco_relative_pose"));

    // PRINT POSE
    //    cout << "arm pose : [" <<   arm_pose_before_grasp.getOrigin().getX() << ", " <<
    //            arm_pose_before_grasp.getOrigin().getY() << ", " <<
    //            arm_pose_before_grasp.getOrigin().getZ() << "]" << endl;

}

void Communication::repeat(){

}

<|endoftext|>


<commit_before>#include <QTest>
#include <QSignalSpy>
#include <QTcpServer>
#include <QTcpSocket>
#include <QRegularExpression>
#include <QBuffer>

#include <neovimconnector.h>

namespace NeovimQt {

class Test: public QObject
{
	Q_OBJECT
private slots:

	void reconnect() {
		NeovimConnector c(new QBuffer());
		QCOMPARE(c.canReconnect(), false);

		NeovimConnector *spawned = NeovimConnector::spawn();
		QCOMPARE(spawned->canReconnect(), true);

		spawned->reconnect();
	}

};

} // Namespace NeovimQt
QTEST_MAIN(NeovimQt::Test)
#include "tst_neovimconnector.moc"
<commit_msg>tests: NeovimConnector::encode/decode and isReady<commit_after>#include <QTest>
#include <QSignalSpy>
#include <QTcpServer>
#include <QTcpSocket>
#include <QRegularExpression>
#include <QBuffer>

#include <neovimconnector.h>
#include "common.h"

namespace NeovimQt {

class Test: public QObject
{
	Q_OBJECT
private slots:

	void reconnect() {
		NeovimConnector c(new QBuffer());
		QCOMPARE(c.canReconnect(), false);

		NeovimConnector *spawned = NeovimConnector::spawn();
		QCOMPARE(spawned->canReconnect(), true);

		spawned->reconnect();
	}

	void isReady() {

		NeovimConnector *c = NeovimConnector::spawn();
		QSignalSpy onReady(c, SIGNAL(ready()));
		QVERIFY(onReady.isValid());

		QVERIFY(SPYWAIT(onReady));
		QVERIFY(c->isReady());
	}

	void encodeDecode() {
		NeovimConnector *c = NeovimConnector::spawn();

		// This will print a warning, but should succeed
		QString s = "ç日本語";
		QByteArray bytes = c->encode(s);
		QCOMPARE(c->decode(bytes), s);

		QSignalSpy onReady(c, SIGNAL(ready()));
		QVERIFY(onReady.isValid());
		QVERIFY(SPYWAIT(onReady));

		bytes = c->encode(s);
		QCOMPARE(c->decode(bytes), s);

	}
};

} // Namespace NeovimQt
QTEST_MAIN(NeovimQt::Test)
#include "tst_neovimconnector.moc"
<|endoftext|>


<commit_before>#include "unittest.h"
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

using namespace rapidjson;

TEST(Writer, Compact) {
	StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ");
	StringBuffer buffer;
	Writer<StringBuffer> writer(buffer);
	Reader reader;
	reader.Parse<0>(s, writer);
	EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3]}", buffer.GetString());
}

// json -> parse -> writer -> json
#define TEST_ROUNDTRIP(json) \
	{ \
		StringStream s(json); \
		StringBuffer buffer; \
		Writer<StringBuffer> writer(buffer); \
		Reader reader; \
		reader.Parse<0>(s, writer); \
		EXPECT_STREQ(json, buffer.GetString()); \
	}

TEST(Writer, Int) {
	TEST_ROUNDTRIP("[-1]");
	TEST_ROUNDTRIP("[-123]");
	TEST_ROUNDTRIP("[-2147483648]");
}

TEST(Writer, UInt) {
	TEST_ROUNDTRIP("[0]");
	TEST_ROUNDTRIP("[1]");
	TEST_ROUNDTRIP("[123]");
	TEST_ROUNDTRIP("[2147483647]");
	TEST_ROUNDTRIP("[4294967295]");
}

TEST(Writer, Int64) {
	TEST_ROUNDTRIP("[-1234567890123456789]");
	TEST_ROUNDTRIP("[-9223372036854775808]");
}

TEST(Writer, Uint64) {
	TEST_ROUNDTRIP("[1234567890123456789]");
	TEST_ROUNDTRIP("[9223372036854775807]");
}

TEST(Writer, String) {
	TEST_ROUNDTRIP("[\"Hello\"]");
	TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
	TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]");
}

TEST(Writer, Transcode) {
	// UTF8 -> UTF16 -> UTF8
	StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3], \"dollar\":\"\x24\", \"cents\":\"\xC2\xA2\", \"euro\":\"\xE2\x82\xAC\", \"gclef\":\"\xF0\x9D\x84\x9E\" } ");
	StringBuffer buffer;
	Writer<StringBuffer, UTF16<>, UTF8<> > writer(buffer);
	GenericReader<UTF8<>, UTF16<> > reader;
	reader.Parse<0>(s, writer);
	EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"dollar\":\"\x24\",\"cents\":\"\xC2\xA2\",\"euro\":\"\xE2\x82\xAC\",\"gclef\":\"\xF0\x9D\x84\x9E\"}", buffer.GetString());
}<commit_msg>Added GenericStringBuffer::GetSize() within unit test, as in 0.1x branch.<commit_after>#include "unittest.h"
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

using namespace rapidjson;

TEST(Writer, Compact) {
	StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ");
	StringBuffer buffer;
	Writer<StringBuffer> writer(buffer);
	Reader reader;
	reader.Parse<0>(s, writer);
	EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3]}", buffer.GetString());
	EXPECT_EQ(77, buffer.GetSize());
}

// json -> parse -> writer -> json
#define TEST_ROUNDTRIP(json) \
	{ \
		StringStream s(json); \
		StringBuffer buffer; \
		Writer<StringBuffer> writer(buffer); \
		Reader reader; \
		reader.Parse<0>(s, writer); \
		EXPECT_STREQ(json, buffer.GetString()); \
	}

TEST(Writer, Int) {
	TEST_ROUNDTRIP("[-1]");
	TEST_ROUNDTRIP("[-123]");
	TEST_ROUNDTRIP("[-2147483648]");
}

TEST(Writer, UInt) {
	TEST_ROUNDTRIP("[0]");
	TEST_ROUNDTRIP("[1]");
	TEST_ROUNDTRIP("[123]");
	TEST_ROUNDTRIP("[2147483647]");
	TEST_ROUNDTRIP("[4294967295]");
}

TEST(Writer, Int64) {
	TEST_ROUNDTRIP("[-1234567890123456789]");
	TEST_ROUNDTRIP("[-9223372036854775808]");
}

TEST(Writer, Uint64) {
	TEST_ROUNDTRIP("[1234567890123456789]");
	TEST_ROUNDTRIP("[9223372036854775807]");
}

TEST(Writer, String) {
	TEST_ROUNDTRIP("[\"Hello\"]");
	TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
	TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]");
}

TEST(Writer, Transcode) {
	// UTF8 -> UTF16 -> UTF8
	StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3], \"dollar\":\"\x24\", \"cents\":\"\xC2\xA2\", \"euro\":\"\xE2\x82\xAC\", \"gclef\":\"\xF0\x9D\x84\x9E\" } ");
	StringBuffer buffer;
	Writer<StringBuffer, UTF16<>, UTF8<> > writer(buffer);
	GenericReader<UTF8<>, UTF16<> > reader;
	reader.Parse<0>(s, writer);
	EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"dollar\":\"\x24\",\"cents\":\"\xC2\xA2\",\"euro\":\"\xE2\x82\xAC\",\"gclef\":\"\xF0\x9D\x84\x9E\"}", buffer.GetString());
}<|endoftext|>