Quote:I think I see what you're saying, but how would the parser know which functions to call from ObJCallback? Are they predefined and the user has to implement them?
Since you mentioned patterns, start with the whole development methodology. How will user use your class? The "story", or "use-case".
Parser p("myfile.obj");p.parse(myCallback);
A file, unless you support includes or shell commands, is parsed top-to-bottom as a whole. The result is a set of structures.
Callback instance will therefore contain the entire state of what is represented in file.
Parser goes through file, line by line, extracting commands. Some commands may span multiple lines in same way C/C++ macros do ('\'). First word of a command always identifies the command.
To determine the format of each command, use the
complete reference. You'll notice that they are quite trivial to parse, and have fixed format.
For example, vertex ('v') has the following form:
v x y z w
If w is not defined in file (if there are only 3 values), w defaults to 1.0. If not all x,y,z are defined, it's an invalid vertex, and you may abort.
Therefore you have your callback:
void addVertex(float x, float y, float z, float w);
Now you can implement a simple callback:
struct MyCallback : public ObjCallback { virtual void addVertex(float x, float y, float z, float w) { vertices.push_back(Vertex4D(x,y,z,w)); } std::vector<Vertex4D> vertices;};
To expand on original example:
MyCallback myCallback;Parser p("myfile.obj");p.parse(&myCallback);std::cout << "File contains: " << myCallback.vertices.size() << " vertices.";
Note that Vertex4D and vertices are user defined structures. Library passes values via function parameters and doesn't impose any structure at all.
Now all that's left is to go through specification, and define parser for each command, and appropriately convenient callback.
Another example - pre-allocating memory:
struct CountCallback : ObjCallback { CountCallback() : nVertices(0) {} virtual void addVertex(float x, float y, float z, float w) { nVertices++; } int nVertices;};struct PreAllocatedCallback : ObjCallback { PreAllocatedCallback(int nVertices) : vertices( new Vertex4D(nVertices) ) , n(0) {} virtual void addVertex(float x, float y, float z, float w) { vertices[n].x = x; vertices[n].y = y; vertices[n].z = z; vertices[n].x = w; n++; } Vertex4D * vertices; int n;};.... Parser p("myFile.obj"); // first, parse the file to count the vertices CountCallback ccb; p.parse(&ccb); // parse again to read the vertex values // now that we know how many there are PreAllocatedCallback pcb(ccb.nVertices); p.parse(&pcb);