-
-
Save BlockoS/2408974 to your computer and use it in GitHub Desktop.
Some VBO Stuff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef XDR_ASSET_H | |
#define XDR_ASSET_H | |
// Asset Management. | |
// Parsing : Human readable data in buffer to object. | |
// | |
/* | |
* <object id="..."> | |
* <array method="TRIANGLES/STRIP/QUAD" material="materialID"> | |
* <point x="..." y="..." z="..." r="..." g="..." b="..." u="..." v="..."/> | |
* <!-- ... --> | |
* </array> | |
* </object> | |
*/ | |
// Hypothesis : Always 3 coordinates for points. | |
// Always 3 coordinates for color. | |
class Array { | |
private: | |
// Vertex Buffer Object identifier. | |
GLuint id; | |
// Number of vertices. | |
unsigned int numVert; | |
// Offset of the color array inside the VBO. | |
unsigned int colorOffset; | |
// Offset of the normal array inside the VBO. | |
unsigned int normalOffset; | |
// Offset of the texture coordinate inside the VBO. | |
unsigned int textureOffset; | |
// Drawing Method (e.g. GL_TRIANGLES). | |
GLuint method; | |
}; | |
// - Initialise/Allocate VBO. | |
/* | |
* glGenBuffers(1, &id); | |
* glBindBuffer(GL_ARRAY_BUFFER, id); | |
* glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); | |
* glBindBuffer(GL_ARRAY_BUFFER, 0); | |
*/ | |
// Displaying : using object to display with VBO. | |
// - GL Rendering routines. | |
/* | |
* glBindBuffer(GL_ARRAY_BUFFER, id); | |
* glVertexPointer(numVertexCoord, typeV, 0, NULL); // typeV is usually GL_FLOAT | |
* glColorPointer(numColorCoord, typeC, 0, offsetColor); // typeC is usually GL_FLOAT | |
* glEnableClientState(GL_VERTEX_ARRAY); // Move this at the begining of all the managed objects display. | |
* glEnableClientState(GL_COLOR_ARRAY); | |
* glDrawArrays(method, 0, numPoint); | |
* glDisableClientState(GL_VERTEX_ARRAY); // Move this at the end of all the managed objects display. | |
* glDisableClientState(GL_COLOR_ARRAY); | |
*/ | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "BufferObject.h" | |
BufferObject::BufferObject() : | |
_id(0), | |
_target(GL_NONE), | |
_size(0), | |
_usage(0) | |
{} | |
BufferObject::~BufferObject() {} | |
bool BufferObject::Create(GLint target, GLsizei size, GLenum usage, const GLvoid *data) | |
{ | |
if(_id) | |
{ | |
Destroy(); | |
} | |
_target = target; | |
_size = size; | |
_usage = usage; | |
glGenBuffers(1, &_id); | |
glBindBuffer(_target, _id); | |
glBufferData(_target, _size, data, GL_STATIC_DRAW); | |
GLenum err = glGetError(); | |
glBindBuffer(_target, 0); | |
if(err != GL_NO_ERROR) | |
{ | |
std::cerr << "An error occured while creating buffer object" << _id << " : " << gluErrorString(err) << std::endl; | |
return false; | |
} | |
return true; | |
} | |
void BufferObject::Destroy() | |
{ | |
if(!_id) | |
return; | |
Unbind(); | |
glDeleteBuffers(1, &_id); | |
_id = 0; | |
} | |
void BufferObject::Unbind() const | |
{ | |
GLuint boundId; | |
GLenum binding; | |
switch(_target) | |
{ | |
case GL_ARRAY_BUFFER: | |
binding = GL_ARRAY_BUFFER_BINDING; | |
break; | |
case GL_ELEMENT_ARRAY_BUFFER: | |
binding = GL_ELEMENT_ARRAY_BUFFER_BINDING; | |
break; | |
case GL_TEXTURE_BUFFER: | |
binding = GL_TEXTURE_BINDING_BUFFER; | |
break; | |
case GL_PIXEL_PACK_BUFFER: | |
binding = GL_PIXEL_PACK_BUFFER_BINDING; | |
break; | |
case GL_PIXEL_UNPACK_BUFFER: | |
binding = GL_PIXEL_UNPACK_BUFFER_BINDING; | |
break; | |
default: | |
glBindBuffer(_target, 0); | |
return; | |
}; | |
glGetIntegerv(binding, (GLint*)&boundId); | |
if(boundId != _id) return; | |
glBindBuffer(_target, 0); | |
} | |
bool BufferObject::SetData( GLintptr offset, GLsizeiptr size, const GLvoid* data ) | |
{ | |
if(offset >= _size) | |
{ | |
std::cerr << "Offset (" << offset << ") out of bound (vbo size: " << _size << ")" << std::endl; | |
return false; | |
} | |
if((offset+size) > _size) | |
{ | |
std::cerr << "Buffer overflow (offset: " << offset << ", size: " << size << ", vbo size: " << _size << ')' << std::endl; | |
return false; | |
} | |
glBindBuffer(_target, _id); | |
glBufferSubData(_target, offset, size, data); | |
glBindBuffer(_target, 0); | |
return true; | |
} | |
GLvoid* BufferObject::MapRange(MappingMode mode, GLintptr offset, GLsizei size) | |
{ | |
GLvoid* ptr; | |
glBindBuffer(_target, _id); | |
ptr = glMapBufferRange(_target, offset, size, ((mode == BUFFER_READ) ? GL_MAP_READ_BIT : (GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)) | GL_MAP_UNSYNCHRONIZED_BIT); | |
if(ptr == NULL) | |
{ | |
GLenum err = glGetError(); | |
std::cerr << "An error occured while mapping buffer object " << _id << " : " << gluErrorString(err) << std::endl; | |
return false; | |
} | |
return ptr; | |
} | |
void BufferObject::Unmap() | |
{ | |
/* todo : get the bound id and check if it's mapped | |
GLint mapped; | |
glGetBufferParameteriv(_target, GL_BUFFER_MAPPED, &mapped); | |
*/ | |
glUnmapBuffer(GL_TEXTURE_BUFFER); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef BUFFER_OBJECT_H | |
#define BUFFER_OBJECT_H | |
// todo: gl includes | |
class BufferObject | |
{ | |
public: | |
BufferObject(); | |
~BufferObject(); | |
bool Create(GLint target, GLsizei size, GLenum usage, const GLvoid *data = NULL); | |
void Destroy(); | |
inline void Bind() const; | |
inline void BindBase(GLenum bindTarget, GLuint index) const; | |
inline void BindRange(GLenum bindTarget, GLuint index, GLintptr offset, GLsizeiptr size) const; | |
void Unbind() const; | |
bool SetData(GLintptr offset, GLsizeiptr size, const GLvoid* data); | |
enum MappingMode | |
{ | |
BUFFER_READ, | |
BUFFER_WRITE | |
}; | |
GLvoid* MapRange(MappingMode mode, GLintptr offset, GLsizei size); | |
void Unmap(); | |
GLuint Id () const { return _id; } | |
GLint Target() const { return _target; } | |
GLint Size () const { return _size; } | |
protected: | |
GLuint _id; | |
GLint _target; | |
GLint _size; | |
GLenum _usage; | |
}; | |
void BufferObject::Bind() const | |
{ | |
glBindBuffer(_target, _id); | |
} | |
void BufferObject::BindBase(GLenum bindTarget, GLuint index) const | |
{ | |
glBindBufferBase(bindTarget, index, _id); | |
} | |
void BufferObject::BindRange(GLenum bindTarget, GLuint index, GLintptr offset, GLsizeiptr size) const | |
{ | |
glBindBufferRange(bindTarget, index, _id, offset, size); | |
} | |
#endif // BUFFER_OBJECT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "microengine.h" | |
#include <GL/glfw.h> | |
#include <iostream> | |
int main(void) { | |
std::cout << "Model ..." << std::endl; | |
Model model(5); | |
std::cout << "Interpreter ..." << std::endl; | |
Interpreter interpreter(&model); | |
std::cout << "Display ..." << std::endl; | |
Display display(&model, &interpreter); | |
std::cout << "Loop ..." << std::endl; | |
if(display.initialize()) | |
display.loop(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
microengine.o: microengine.h microengine.c | |
g++ -c microengine.C -I. -I../common | |
main.o: microengine.h main.c | |
g++ -c main.c -I. -I../common | |
all: main.o microengine.o | |
g++ main.o microengine.o -lGL -lglfw -lm -lpthread -o speedcoding |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Mesh.h" | |
Mesh::Mesh() : | |
_vertexCount(0), | |
_elementCount(0), | |
_elementSize(0), | |
_vao(0), | |
_vbo(), | |
_pritimive() | |
{} | |
Mesh::~Mesh() | |
{} | |
bool Mesh::Create(const GLfloat* vertexBuffer, int nVertices, const GLuint* triList, int nElements) | |
{ | |
_vertexCount = nVertices; | |
_elementCount = 0; | |
if(!_vbo.Create(GL_ARRAY_BUFFER, _vertexCount * sizeof(GLfloat[8]), GL_STATIC_DRAW, vertexBuffer)) | |
{ | |
std::cerr << "An error occured during vertex data creation!" << std::endl; | |
return false; | |
} | |
_elementSize = nElements * 3; | |
if(!_pritimive.Create(GL_ELEMENT_ARRAY_BUFFER, _elementSize * sizeof(GLuint), GL_STATIC_DRAW, triList)) | |
{ | |
std::cerr << "An error occured during primitive element creation!" << std::endl; | |
_vbo.Destroy(); | |
return false; | |
} | |
glGenVertexArrays(1, &_vao); | |
glBindVertexArray(_vao); | |
glEnableVertexAttribArray(0); | |
glEnableVertexAttribArray(1); | |
glEnableVertexAttribArray(2); | |
_vbo.Bind(); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); | |
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(_vertexCount * sizeof(GLfloat[3]))); | |
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(_vertexCount * sizeof(GLfloat[5]))); | |
_vbo.Unbind(); | |
_pritimive.Bind(); | |
glBindVertexArray(0); | |
// todo: get glerror and check if anything nasty occured. | |
return true; | |
} | |
void Mesh::Destroy() | |
{ | |
glDeleteVertexArrays(1, &_vao); | |
_vbo.Destroy(); | |
_pritimive.Destroy(); | |
} | |
void Mesh::Render() | |
{ | |
glBindVertexArray(_vao); | |
glDrawElements(GL_TRIANGLES, _elementSize, GL_UNSIGNED_INT, 0); | |
glBindVertexArray(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef MESH_H | |
#define MESH_H | |
#include "BufferObject.h" | |
class Mesh | |
{ | |
public: | |
Mesh(); | |
~Mesh(); | |
// Create object | |
bool Create(const GLfloat* vertexBuffer, int nVertices, const GLuint* triList, int nElements); | |
// Destroy object | |
virtual void Destroy(); | |
// Render object | |
virtual void Render(); | |
GLsizei VertexCount () const { return _vertexCount; } | |
GLsizei ElementCount() const { return _elementCount; } | |
GLuint VAO() const { return _vao; }; | |
protected: | |
// Create a vao | |
virtual bool CreateVao(); | |
protected: | |
GLuint _vao; | |
GLsizei _vertexCount; | |
GLsizei _elementCount; | |
GLint _elementSize; | |
// Point + tex + normal | |
BufferObject _vbo; | |
BufferObject _pritimive; | |
AttributeInfo _pointCoordInfo; | |
AttributeInfo _texCoordInfo; | |
AttributeInfo _normalInfo; | |
ElementInfo _primitiveInfo; | |
}; | |
#endif // MESH_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "microengine.h" | |
#include <GL/glfw.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <iostream> | |
Interpreter *Interpreter::current = 0; | |
Model::Model(unsigned int c) { | |
flag = 0; | |
lastUpdate = 0; | |
std::cout << "Allocate volumes ..." << std::endl; | |
volume = new Volume*[c]; | |
volumeCapacity = c; | |
std::cout << "Initialise volumes : " << std::flush; | |
for(int i = 0; i < c; ++i) { | |
std::cout << i << " " << std::flush; | |
volume[i] = 0; | |
} | |
volumeCount = 1; | |
std::cout << std::endl << "Initialise first volume." << std::endl; | |
volume[0] = new Volume(1, 0); | |
} | |
Model::~Model() { | |
for(int i = 0; i < volumeCount; ++i) { | |
// We assume that volumes aren't null between 0 and volumeCount. | |
delete volume[i]; | |
} | |
delete [] volume; | |
} | |
void Model::tick() { | |
pthread_mutex_lock(&mutex); | |
double currentTime = glfwGetTime(); | |
double elapsed = currentTime - lastUpdate; | |
// Ok, given the elapsed time and the logical event, let's do some stuff. | |
double x = volume[0]->getX(); | |
double y = volume[0]->getY(); | |
double z = volume[0]->getZ(); | |
double angle = volume[0]->getAngle(); | |
double forwardProg = ( (((flag & LEVENT_FORWARD) != 0)?1:0)+ | |
(((flag & LEVENT_BACK) != 0)?-1:0) ) * elapsed * 2; | |
// Speed is 1 unit/s. | |
double angleProg = ( (((flag & LEVENT_LEFT) != 0)?-1:0)+ | |
(((flag & LEVENT_RIGHT) != 0)?1:0) ) * elapsed * 200; | |
// Angular speed is 200 deg/s. | |
angle += angleProg; | |
angleProg = (angle * 3.141516) / 180.0; | |
x += cos(angleProg) * forwardProg; | |
z += sin(angleProg) * forwardProg; | |
volume[0]->setAngle(angle); | |
volume[0]->setPosition(x, y, z); | |
// TODO Update other volumes. | |
lastUpdate = currentTime; | |
pthread_mutex_unlock(&mutex); | |
} | |
Volume **Model::getVolume() { | |
Volume **rc; | |
pthread_mutex_lock(&mutex); | |
rc = volume; | |
// TODO Model Double Buffering. | |
pthread_mutex_unlock(&mutex); | |
return rc; | |
} | |
void Model::start() { | |
threadFlag = true; | |
pthread_attr_t attr; | |
pthread_mutex_init(&mutex, 0); | |
pthread_attr_init(&attr); | |
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | |
pthread_create(&thread, &attr, Model::run, this); | |
pthread_attr_destroy(&attr); | |
// TODO Error management. | |
} | |
void Model::stop() { | |
threadFlag = false; | |
if(thread != 0) { | |
void *status; | |
pthread_join(thread, &status); | |
pthread_mutex_destroy(&mutex); | |
} | |
} | |
void *Model::run(void *subject) { | |
Model *model = static_cast<Model*>(subject); | |
if(0 == model) { | |
return 0; | |
} | |
while(model->threadFlag) { | |
model->tick(); | |
usleep(45000); | |
} | |
} | |
void Interpreter::addKeyEvent(int key, int action) { | |
unsigned char flag = 0; | |
switch(key) { | |
case GLFW_KEY_UP: | |
flag = LEVENT_FORWARD; | |
break; | |
case GLFW_KEY_DOWN: | |
flag = LEVENT_BACK; | |
break; | |
case GLFW_KEY_LEFT: | |
flag = LEVENT_LEFT; | |
break; | |
case GLFW_KEY_RIGHT: | |
flag = LEVENT_RIGHT; | |
break; | |
case GLFW_KEY_ESC: | |
exit(1); // SHBLAM ! | |
break; | |
default: | |
break; | |
} | |
if(action == GLFW_PRESS) { | |
model->addFlag(flag); | |
} else { | |
model->removeFlag(flag); | |
} | |
} | |
void GLFWCALL manageSystemKeyboardEvent(int key, int action) { | |
Interpreter *interpreter = Interpreter::getCurrent(); | |
interpreter->addKeyEvent(key, action); | |
} | |
bool Display::initialize() { | |
if(glfwInit() != GL_TRUE) { | |
return false; | |
} | |
int window_width = 800; | |
int window_height = 600; | |
if (glfwOpenWindow(window_width, window_height, 8, 8, 8, | |
0, 0, 0, GLFW_WINDOW) != GL_TRUE) | |
return false; | |
glfwSetWindowTitle("The GLFW Window"); | |
glfwSetKeyCallback(manageSystemKeyboardEvent); | |
// set the projection matrix to a normal frustum with a max depth of 50 | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
float aspect_ratio = ((float)window_height) / window_width; | |
glFrustum(.5, -.5, -.5 * aspect_ratio, .5 * aspect_ratio, 1, 50); | |
glMatrixMode(GL_MODELVIEW); | |
return true; | |
} | |
void Display::loop() { | |
model->start(); | |
while(1) { | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
draw(); | |
// model->tick(); // In real life, this tick is done in a different thread. | |
glfwSwapBuffers(); | |
} | |
} | |
void Display::draw() { | |
glLoadIdentity(); | |
glTranslatef(0, 0, -30); | |
Volume **v = model->getVolume(); | |
unsigned int count = model->getCount(); | |
for(int i = 0; i < count; ++i, ++v) { | |
glTranslatef((*v)->getX(), (*v)->getZ(), 0); | |
glRotatef((*v)->getAngle(), 0, 0, 1); | |
glBegin(GL_QUADS); | |
glColor3f(0, 0, 1); | |
glVertex2d(-0.5, -0.5); | |
glVertex2d(0.5, -0.5); | |
glVertex2d(0.5, 0.5); | |
glVertex2d(-0.5, 0.5); | |
glEnd(); | |
glBegin(GL_LINES); | |
glVertex2d(0, 0); | |
glVertex2d(1, 0); | |
glEnd(); | |
} | |
} | |
Display::~Display() { | |
// Nada | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _MICRO_ENGINE_H_ | |
#define _MICRO_ENGINE_H_ | |
#include <GL/glfw.h> | |
#include <pthread.h> | |
// The so-called volume class is a cube/stuff with orientation on Y axis. | |
class Volume { | |
public: | |
Volume(double s, double a) : size(s), angle(a), x(0), y(0), z(0) {} | |
inline double getSize() { return size; } | |
inline double getAngle() { return angle; } | |
inline double getX() { return x; } | |
inline double getY() { return y; } | |
inline double getZ() { return z; } | |
void setSize(double s) { size = s; } | |
void setAngle(double a) { angle = a; } | |
void setPosition(double pX, double pY, double pZ) { | |
x = pX; y = pY; z = pZ; | |
} | |
private: | |
double size; | |
double angle; | |
double x; | |
double y; | |
double z; | |
}; | |
#define LEVENT_FORWARD 1 | |
#define LEVENT_BACK 2 | |
#define LEVENT_LEFT 4 | |
#define LEVENT_RIGHT 8 | |
#define LEVENT_JUMP 16 | |
// The model/scene is quite simple. For this speedcoding session, | |
// it only consists in a single volume. | |
class Model { | |
public: | |
Model(unsigned int); // Number of volume to manage. | |
~Model(); | |
void setLastUpdate(double d) { lastUpdate = d; } | |
// Update tick. | |
void tick(); | |
// Models retrieval. | |
Volume **getVolume(); | |
unsigned int getCount() { return volumeCount; } | |
void addFlag(unsigned char fl) { flag |= fl; } | |
void removeFlag(unsigned char fl) { flag &= ~fl; }; | |
unsigned char getFlag() { return flag; } | |
void start(); | |
void stop(); | |
private: | |
// The flag indicate which are the logical event in hold. | |
unsigned char flag; | |
Volume **volume; | |
unsigned int volumeCount; | |
unsigned int volumeCapacity; | |
double lastUpdate; | |
pthread_t thread; | |
pthread_mutex_t mutex; | |
bool threadFlag; | |
private: | |
static void *run( void * ); | |
}; | |
/* | |
* It is this guy who react to events. | |
* It will modify the model accordingly. | |
* | |
* In fact, it's a bit more complicated. | |
* The thing is that the interpreter gets | |
* system event, the current state of the world | |
* and generate logic events accordingly. | |
* | |
* Then, logic events, in conjunction with | |
* the current state of the world, generate | |
* world updates. | |
*/ | |
class Interpreter { | |
public: | |
Interpreter(Model *m) : model(m) { current = this; } | |
// Add a system event based on keyboard. | |
void addKeyEvent(int key, int action); | |
static Interpreter *getCurrent() { return current; } | |
private: | |
static Interpreter *current; | |
Model *model; | |
}; | |
void GLFWCALL manageSystemKeyboardEvent(int key, int action); | |
/* | |
* And finally, the display ! | |
* This kind guy takes what's in the model and simply display it. | |
* How nice is that ? | |
*/ | |
class Display { | |
public: | |
Display(Model *m, Interpreter *i) : model(m), interpreter(i) {} | |
bool initialize(); | |
void loop(); | |
~Display(); | |
private: | |
void draw(); | |
private: | |
Interpreter *interpreter; | |
Model *model; | |
}; | |
#endif | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Parsing handler using expat engine. */ | |
#ifndef _PARSER_HANDLER_H_ | |
#define _PARSER_HANDLER_H_ | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <expat.h> | |
#define PARSER_HANDLER_BUFFER_SIZE 65536 | |
/** | |
* Parser are parametrized with class implementing the following concept. | |
* | |
* void startElement(const XML_Char *, const XML_Char **); | |
* void endElement(const XML_Char *); | |
* | |
*/ | |
template <typename T> class Parser { | |
public: | |
static void parse(T *target, const char *filename) { | |
char buffer[PARSER_HANDLER_BUFFER_SIZE]; | |
int handle = open(filename, O_RDONLY); | |
ssize_t rdLen; | |
if(handle < 0) { | |
// TODO ERROR | |
return; | |
} | |
XML_Parser parser = XML_ParserCreate(NULL); | |
XML_SetUserData(parser, target); | |
XML_SetElementHandler(parser, startElementHandler, endElementHandler); | |
while((rdLen = read(handle, buffer, PARSER_HANDLER_BUFFER_SIZE)) > 0) { | |
if(!XML_Parse(parser, | |
buffer, | |
rdLen, | |
rdLen < PARSER_HANDLER_BUFFER_SIZE)) { | |
// TODO ERROR | |
break; | |
} | |
} | |
XML_ParserFree(parser); | |
close(handle); | |
} | |
private: | |
static void startElementHandler(void *data, | |
const XML_Char *name, | |
const XML_Char **atts) { | |
T* t = (T *) data; | |
t->startElement(name, atts); | |
} | |
static void endElementHandler(void *data, | |
const XML_Char *name) { | |
T *t = (T *) data; | |
t->endElement(name); | |
} | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment