Skip to content

Instantly share code, notes, and snippets.

@moyix
Created March 8, 2024 22:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moyix/dc15f77a51c380df9bb5b3a1bc36389c to your computer and use it in GitHub Desktop.
Save moyix/dc15f77a51c380df9bb5b3a1bc36389c to your computer and use it in GitHub Desktop.
Claude 3 writes a fuzzer for VRML files

C++ files are are from this GitHub repository, with a small modification by me to allow the parser to accept a filename on the command line:

https://github.com/alepapadop/vrml

genvrml_v*.py written by Claude 3 Opus.

The conversation was:

Initial Prompt

(Attached files: data_types.cpp, data_types.h, main.cpp, vrml_parser.cpp, vrml_parser.h)

Given this C++ program, can you write a Python function that generates random VRML files that fully exercise the parsing code? The function should have the signature:

# Generates a random file into `out`
def generate_random_input(out: BinaryIO):

Claude

Here's a Python function that generates random VRML files to exercise the parsing code you provided:

[Attached: genvrml_v0.py]

This function generates random VRML files by constructing different node types and their fields based on probabilities. It supports the following node types:

  • Shape: Generates a Shape node with optional Appearance and geometry (PointSet, IndexedLineSet, or IndexedFaceSet).
  • Transform: Generates a Transform node with optional translation, rotation, and scale fields. It also recursively generates children nodes.
  • PointSet: Generates a PointSet node with random points.

The function also includes a probability to add DEF/USE statements to test the parsing of these constructs.

You can adjust the probabilities, ranges, and node types based on your specific testing requirements.

To use the function, you can simply call it with a binary file object, and it will write the generated VRML content to the file. In the example usage, it generates a random VRML file named "random.wrl".

Note: Make sure to have the necessary imports and Python version that supports the BinaryIO type hint.

Me

I get:

Traceback (most recent call last):
  File "/Users/moyix/git/vrml/genvrml.py", line 112, in <module>
    generate_random_input(of)
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
  File "/Users/moyix/git/vrml/genvrml.py", line 105, in generate_random_input
    generate_random_input(out)
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
  [Previous line repeated 9 more times]
  File "/Users/moyix/git/vrml/genvrml.py", line 63, in generate_random_input
    out.write(f"{indices[i]}, {indices[i+1]}, {indices[i+2]}, -1,\n".encode())
                               ~~~~~~~^^^^^
IndexError: list index out of range

Claude

Apologies for the oversight in the IndexedFaceSet generation. Here's the corrected version of the generate_random_input function:

[Attached: genvrml_v1.py]

The issue was in the IndexedFaceSet generation, specifically in the loop that writes the coordIndex field. The loop was not properly handling the case when the number of points is not divisible by 3.

I've updated the loop to iterate up to num_points - 2 with a step of 3, ensuring that there are always enough points to form a triangle.

for i in range(0, num_points - 2, 3):
    out.write(f"{indices[i]}, {indices[i+1]}, {indices[i+2]}, -1,\n".encode())

With this correction, the function should generate valid random VRML files without encountering the IndexError.

Me

Now I get:

Traceback (most recent call last):
  File "/Users/moyix/git/vrml/genvrml.py", line 111, in <module>
    generate_random_input(file)
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
  File "/Users/moyix/git/vrml/genvrml.py", line 105, in generate_random_input
    generate_random_input(out)
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
[...]
  File "/Users/moyix/git/vrml/genvrml.py", line 85, in generate_random_input
    generate_random_input(out)
  [Previous line repeated 27 more times]
  File "/Users/moyix/git/vrml/genvrml.py", line 7, in generate_random_input
    num_nodes = random.randint(1, 10)
                ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/moyix/.pyenv/versions/3.12.2/lib/python3.12/random.py", line 336, in randint
    return self.randrange(a, b+1)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/moyix/.pyenv/versions/3.12.2/lib/python3.12/random.py", line 318, in randrange
    return istart + self._randbelow(width)
                    ^^^^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded

Claude

I apologize for the inconvenience caused by the recursive calls. The recursive generation of child nodes in the Transform node can lead to excessive recursion depth in some cases. Let's modify the code to limit the recursion depth and prevent the RecursionError.

Here's the updated version of the generate_random_input function with a maximum recursion depth:

[Attached: genvrml_v2.py]

The main changes are:

  1. The generate_random_input function now takes two additional parameters: max_depth (default value of 5) to limit the maximum recursion depth, and current_depth (default value of 0) to keep track of the current depth.

  2. At the beginning of the function, we check if the current_depth exceeds the max_depth. If so, we return immediately to stop further recursion.

  3. When recursively generating child nodes for the Transform node, we pass the max_depth and current_depth + 1 to the recursive calls.

  4. The number of nodes generated at each level is reduced to a random number between 1 and 5 to limit the overall size of the generated file.

With these modifications, the function should generate valid random VRML files without exceeding the maximum recursion depth. You can adjust the max_depth value according to your needs.

#include "data_types.h"
#include "str_and_math.h"
#include "file_handler.h"
#include "vrml_parser.h"
#include <iostream>
using namespace std;
/*************************************************************************************/
/*************************************************************************************/
void set_node_id(void *node, int id)
{
Info **info = NULL;
info = (Info **)node;
if (info) {
(*info)->id = id;
}
}
/*************************************************************************************/
/*************************************************************************************/
void set_node_type(void *node, DataType type)
{
Info **info = NULL;
info = (Info **)node;
if (info) {
(*info)->type = type;
}
}
/*************************************************************************************/
/*************************************************************************************/
int get_node_id(void *node)
{
Info **info = NULL;
int value = -1;
info = (Info **)node;
if (info) {
value = (*info)->id;
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
DataType get_node_type(void *node)
{
Info **info = NULL;
DataType value = UNKNOWN;
info = (Info **)node;
if (info) {
value = (*info)->type;
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
void check_def_tokn(string tokn)
{
if (tokn.find("DEF") != string::npos) {
gvar->def_flag = 1;
gvar->def_tokn = get_tokn();
}
// unset the def flag when you find the first opening bracket "{"
if (gvar->def_flag && tokn.find("{") != string::npos) {
gvar->def_flag = 0;
gvar->def_tokn = "";
}
}
/*************************************************************************************/
/*************************************************************************************/
void check_use_tokn(string tokn)
{
if (gvar->use_flag) {
gvar->use_flag = 0;
gvar->use_tokn = "";
}
if (tokn.find("USE") != string::npos) {
// prosoxi i seira pou exoun oi netoles einai poli simantiki
gvar->use_tokn = get_tokn();
gvar->use_flag = 1;
}
}
/*************************************************************************************/
/*************************************************************************************/
void add_to_def(string tokn, Container *container)
{
// eukolaki vazeis sto map perneis apo to map
// o kwdika tha mpei mesa stin get_tokn opote
// den tha mplexoume me ta alla
// prepei na kanw kai ta alla na epistrefoun container
// episi na kanw kai to group
// poly testing para poly :)
if (gvar->def_map) {
(*(gvar->def_map))[tokn] = container;
}
gvar->def_flag = 0;
gvar->def_tokn = "";
}
/*************************************************************************************/
/*************************************************************************************/
void add_to_def_map(string tokn, void *data)
{
// eukolaki vazeis sto map perneis apo to map
// o kwdika tha mpei mesa stin get_tokn opote
// den tha mplexoume me ta alla
// prepei na kanw kai ta alla na epistrefoun container
// episi na kanw kai to group
// poly testing para poly :)
if (gvar->def_map2) {
(*(gvar->def_map2))[tokn] = data;
}
gvar->def_flag = 0;
gvar->def_tokn = "";
}
/*************************************************************************************/
/*************************************************************************************/
void* get_from_def(string tokn)
{
//otan epistrefo to grafo amesws sto frame mesw tis global var
Container *container = NULL;
map<string, Container *>::iterator it;
if (gvar->def_map) {
it = gvar->def_map->find(tokn);
if (it != gvar->def_map->end()) {
container = it->second;
}
}
gvar->use_flag = 0;
return container;
}
/*************************************************************************************/
/*************************************************************************************/
Container *new_container()
{
Container *container = NULL;
container = new Container;
return container;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_container(Container *container)
{
delete container;
}
/*************************************************************************************/
/*************************************************************************************/
void set_container_type(Container *container, DataType type)
{
if (container) {
container->type = type;
}
}
/*************************************************************************************/
/*************************************************************************************/
void set_container_data(Container *container, void *data)
{
if (container) {
container->data = data;
}
}
/*************************************************************************************/
/*************************************************************************************/
DataType get_container_type(Container *container)
{
DataType type = UNKNOWN;
if (container) {
type = container->type;
}
return type;
}
/*************************************************************************************/
/*************************************************************************************/
void *get_container_data(Container *container)
{
void *data = NULL;
if (container) {
data = container->data;
}
return data;
}
/*************************************************************************************/
/*************************************************************************************/
void init_node_type_map(map<string, DataType> **node_type_map)
{
if (*node_type_map == NULL) {
*node_type_map = new map<string, DataType>;
}
(**node_type_map)["Shape"] = SHAPE;
(**node_type_map)["Group"] = GROUP;
(**node_type_map)["Coordinate"] = COORDINATE;
(**node_type_map)["IndexedLineSet"] = INDEXED_LINE_SET;
(**node_type_map)["IndexedFaceSet"] = INDEXED_FACE_SET;
(**node_type_map)["Transform"] = TRANSFORM;
(**node_type_map)["Material"] = MATERIAL;
(**node_type_map)["PointSet"] = POINT_SET;
(**node_type_map)["Appearance"] = APPEARANCE;
}
/*************************************************************************************/
/*************************************************************************************/
void init_field_type_map(map<string, DataType> **field_type_map)
{
if (*field_type_map == NULL) {
*field_type_map = new map<string, DataType>;
}
(**field_type_map)["translation"] = TRANSLATION;
(**field_type_map)["rotation"] = ROTATION;
(**field_type_map)["scale"] = SCALE;
(**field_type_map)["point"] = POINT;
}
/*************************************************************************************/
/*************************************************************************************/
DataSup *add_type_sup_map(string keyword, DataType type, READ_NODE_FUN read_node_fun,
READ_FIELD_FUN read_field_fun, CREATE_FUN create_fun)
{
DataSup *data_sup = NULL;
data_sup = new DataSup;
if (data_sup) {
data_sup->keyword = keyword;
data_sup->type = type;
data_sup->read_node_fun = read_node_fun;
data_sup->read_field_fun = read_field_fun;
data_sup->create_fun = create_fun;
}
return data_sup;
}
/*************************************************************************************/
/*************************************************************************************/
void init_type_sup_map(map<DataType, DataSup *> **type_sup_map)
{
if (*type_sup_map == NULL) {
*type_sup_map = new map<DataType, DataSup *>;
}
/* NODE FUNCTIONS */
(**type_sup_map)[COORDINATE] = add_type_sup_map("Coordinate", COORDINATE ,read_coordinate, NULL, NULL);
(**type_sup_map)[POINT_SET] = add_type_sup_map("PointSet", POINT_SET ,read_point_set, NULL, NULL);
(**type_sup_map)[SHAPE] = add_type_sup_map("Shape", SHAPE ,read_shape, NULL, NULL);
(**type_sup_map)[TRANSFORM] = add_type_sup_map("Transform", TRANSFORM, read_transform, NULL, NULL);
/* FIELD FUNCTIONS */
(**type_sup_map)[TRANSLATION] = add_type_sup_map("translation", TRANSLATION, NULL, read_translation, NULL);
(**type_sup_map)[ROTATION] = add_type_sup_map("rotation", ROTATION, NULL, read_rotation, NULL);
(**type_sup_map)[SCALE] = add_type_sup_map("scale", SCALE, NULL, read_scale, NULL);
(**type_sup_map)[POINT] = add_type_sup_map("point", POINT, NULL, read_point, NULL);
}
/*************************************************************************************/
/*************************************************************************************/
void init_frame(vector<Container *> **frame)
{
if (*frame == NULL) {
*frame =new vector<Container *>;
}
}
/*************************************************************************************/
/*************************************************************************************/
void init_def(map<string, Container *> **def)
{
if (*def == NULL) {
*def = new map<string, Container *>;
}
}
/*************************************************************************************/
/*************************************************************************************/
void init_def_map2(map<string, void *> **def_map2)
{
if (*def_map2 == NULL) {
*def_map2 = new map<string, void *>;
}
}
/*************************************************************************************/
/* Point */
/*************************************************************************************/
Point *new_point()
{
Point *point = NULL;
point = new Point;
return point;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_point(Point *point)
{
delete point;
}
/*************************************************************************************/
/*************************************************************************************/
void debug_read_point(vector<Point *> *coordinate_vec)
{
vector<Point *>::iterator it;
Point *point;
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "value: x = " << point->x << " y = " << point->y << " z = " << point->z << endl;
}
}
/*************************************************************************************/
/*************************************************************************************/
void *read_point(void *args)
{
Point *point = NULL;
string tokn = "";
double tmp;
int valid_flag;
int flag = 0;
int count = 0;
double x, y, z;
vector<Point *> *coordinate_vec = NULL;
cout << "Hello read point" << endl;
coordinate_vec = new vector<Point *>;
while (tokn.find("]") == string::npos) {
tokn = get_tokn();
flag = 0;
if (find_comma_and_remove_it(&tokn) || tokn.find(",") != string::npos || count == 3) {
//cout << "tokn " << tokn << endl;
flag = 1;
}
if (is_number(tokn)) {
valid_flag = 1;
tmp = str2double(tokn, &valid_flag);
if (valid_flag) {
if (count == 0) {
x = tmp;
} else if (count == 1) {
y = tmp;
} else if (count == 2) {
z = tmp;
}
}
count ++;
}
if (flag == 1) {
point = new_point();
if (point) {
point->x = x;
point->y = y;
point->z = z;
count = 0;
flag = 0;
//cout << "read point value: x = " << point->x << " y = " << point->y << " z = " << point->z << endl;
}
if (coordinate_vec) {
coordinate_vec->push_back(point);
}
point = NULL;
}
}
//debug_read_point(coordinate_vec);
return coordinate_vec;
}
/*************************************************************************************/
/* CoordIndex */
/*************************************************************************************/
CoordIndex *new_coord_index()
{
CoordIndex *coord_index = NULL;
vector<int> *coord_index_vec = NULL;
coord_index = new CoordIndex;
if (coord_index) {
coord_index_vec = new vector<int>;
coord_index->coord_index_vec = coord_index_vec;
}
return coord_index;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_coord_index(CoordIndex *coord_index)
{
delete coord_index->coord_index_vec;
delete coord_index;
}
/*************************************************************************************/
/* Coordinate */
/*************************************************************************************/
Coordinate *new_coordinate()
{
Coordinate *coordinate = NULL;
vector<Point *> *coordinate_vec = NULL;
coordinate = new Coordinate;
if (coordinate) {
//coordinate_vec = new vector<Point *>;
coordinate->info = new Info;
coordinate->coordinate_vec = coordinate_vec;
}
return coordinate;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_coordinate(Coordinate *coordinate)
{
vector<Point *>::iterator it;
vector<Point *> *coordinate_vec;
coordinate_vec = coordinate->coordinate_vec;
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
delete_point(*it);
}
delete coordinate->coordinate_vec;
delete coordinate;
}
/*************************************************************************************/
/*************************************************************************************/
void debug_read_coordinate(Coordinate *coordinate)
{
vector<Point *> *coordinate_vec = NULL;
vector<Point *>::iterator it;
Point *point = NULL;
if (coordinate) {
coordinate_vec = coordinate->coordinate_vec;
if (coordinate_vec) {
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "read_coordinate value: x = " << point->x << " y = " << point->y << " z = " << point->z << endl;
}
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void *read_coordinate(void *data) {
cout << "Hello coordinate" << endl;
string tokn = "";
Coordinate *coordinate = NULL;
coordinate = new_coordinate();
if (coordinate) {
while (tokn.find("}") == string::npos) {
tokn = get_tokn();
if (tokn.find("point") != string::npos) {
coordinate->coordinate_vec = (vector<Point *> *)read_point(coordinate);
}
}
set_node_type(coordinate, COORDINATE);
}
//debug_read_coordinate(coordinate);
return coordinate;
}
/*************************************************************************************/
/* IndexedLineSet */
/*************************************************************************************/
IndexedLineSet *new_indexed_line_set()
{
IndexedLineSet *indexed_line_set = NULL;
Coordinate *coordinate = NULL;
vector<CoordIndex *> *indexed_line_set_vec = NULL;
indexed_line_set = new IndexedLineSet;
if (indexed_line_set) {
coordinate = new_coordinate();
indexed_line_set_vec = new vector<CoordIndex *>;
indexed_line_set->coordinate = coordinate;
indexed_line_set->indexed_line_set_vec = indexed_line_set_vec;
}
return indexed_line_set;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_indexed_line_set(IndexedLineSet *indexed_line_set)
{
vector<CoordIndex *>::iterator it;
vector<CoordIndex *> *indexed_line_set_vec;
indexed_line_set_vec = indexed_line_set->indexed_line_set_vec;
for (it = indexed_line_set_vec->begin(); it != indexed_line_set_vec->end(); ++it) {
delete_coord_index(*it);
}
delete_coordinate(indexed_line_set->coordinate);
delete indexed_line_set;
}
/*************************************************************************************/
/* IndexedFaceSet */
/*************************************************************************************/
IndexedFaceSet *new_indexed_face_set()
{
IndexedFaceSet *indexed_face_set = NULL;
Coordinate *coordinate = NULL;
vector<CoordIndex *> *indexed_face_set_vec = NULL;
indexed_face_set = new IndexedFaceSet;
if (indexed_face_set) {
coordinate = new_coordinate();
indexed_face_set_vec = new vector<CoordIndex *>;
indexed_face_set->coordinate = coordinate;
indexed_face_set->indexed_face_set_vec = indexed_face_set_vec;
}
return indexed_face_set;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_indexed_face_set(IndexedFaceSet *indexed_face_set)
{
vector<CoordIndex *>::iterator it;
vector<CoordIndex *> *indexed_face_set_vec;
indexed_face_set_vec = indexed_face_set->indexed_face_set_vec;
for (it = indexed_face_set_vec->begin(); it != indexed_face_set_vec->end(); ++it) {
delete_coord_index(*it);
}
delete_coordinate(indexed_face_set->coordinate);
delete indexed_face_set;
}
/*************************************************************************************/
/* Material */
/*************************************************************************************/
Material *new_material()
{
Material *material = NULL;
material = new Material;
return material;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_material(Material *material)
{
delete material;
}
/*************************************************************************************/
/* PointSet */
/*************************************************************************************/
PointSet *new_point_set()
{
PointSet *point_set = NULL;
Coordinate *coordinate = NULL;
point_set = new PointSet;
if (point_set) {
//coordinate = new_coordinate();
point_set->info = new Info;
point_set->coordinate = coordinate;
}
return point_set;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_point_set(PointSet *point_set)
{
delete_coordinate(point_set->coordinate);
delete point_set->coordinate;
}
/*************************************************************************************/
/*************************************************************************************/
void debug_read_point_set(PointSet *point_set)
{
Coordinate *coordinate = NULL;
vector<Point *> *coordinate_vec = NULL;
vector<Point *>::iterator it;
Point *point = NULL;
if (point_set) {
coordinate = point_set->coordinate;
if (coordinate) {
coordinate_vec = coordinate->coordinate_vec;
if (coordinate_vec) {
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "r_point_set value: x = " << point->x << " y = " << point->y << " z = " << point->z << endl;
}
}
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void store_data_point_set(PointSet *point_set, void *data)
{
DataType type = UNKNOWN;
if (data) {
type = get_node_type(data);
switch (type) {
case COORDINATE:
point_set->coordinate = (Coordinate *)data;
break;
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void *read_point_set(void *args)
{
cout << "Hello point set" << endl;
PointSet *point_set = NULL;
string tokn = "";
void *data = NULL;
int def_flag = 0;
string def_tokn = "";
point_set = new_point_set();
if (point_set) {
while (tokn.find("}") == string::npos) {
// tokn = get_tokn();
//------------------------------
//Edw prepei na to ksanadw to vrady...
if (gvar->use_flag) {
data = (*gvar->def_map2)[gvar->use_tokn];
store_data_point_set(point_set, data);
}
if (gvar->def_flag) {
def_flag = 1;
def_tokn = gvar->def_tokn;
}
data = NULL;
tokn = get_tokn();
data = call_node_read_function(tokn, NULL);
store_data_point_set(point_set, data);
if (def_flag && data !=NULL) {
add_to_def_map(def_tokn, data);
}
//------------------------------
/*if (tokn.find("Coordinate") != string::npos) {
point_set->coordinate = (Coordinate *)read_coordinate(point_set);
} else if (tokn.find("Color") != string::npos) {
;
}*/
}
set_node_type(point_set, POINT_SET);
}
debug_read_point_set(point_set);
return point_set;
}
/*************************************************************************************/
/* Appearance */
/*************************************************************************************/
Appearance *new_appearance()
{
Appearance *appearance = NULL;
appearance = new Appearance;
return appearance;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_appearance(Appearance *appearance)
{
delete appearance;
}
/*************************************************************************************/
/* Shape */
/*************************************************************************************/
Shape *new_shape()
{
Shape *shape = NULL;
shape = new Shape;
if (shape) {
//shape->appearance = new_appearance();
//shape->point_set = new_point_set();
//shape->indexed_line_set = new_indexed_line_set();
//shape->indexed_face_set = new_indexed_face_set();
shape->info = new Info;
set_node_type(shape, SHAPE);
shape->appearance = NULL;
shape->point_set = NULL;
shape->indexed_line_set = NULL;
shape->indexed_face_set = NULL;
}
return shape;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_shape(Shape *shape)
{
//delete_appearance(shape->appearance);
//delete_point_set(shape->point_set);
//delete_indexed_line_set(shape->indexed_line_set);
//delete_indexed_face_set(shape->indexed_face_set);
delete shape;
}
/*************************************************************************************/
/*************************************************************************************/
void debug_read_shape(void *args)
{
PointSet *point_set = NULL;
Coordinate *coordinate = NULL;
vector<Point *> *coordinate_vec = NULL;
vector<Point *>::iterator it;
Point *point = NULL;
Shape *shape = NULL;
shape = (Shape *) args;
if (shape) {
point_set = shape->point_set;
if (point_set) {
coordinate = point_set->coordinate;
if (coordinate) {
coordinate_vec = coordinate->coordinate_vec;
if (coordinate_vec) {
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "r_shape value: x = " << point->x << " y = " << point->y << " z = "
<< point->z << endl;
}
}
}
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void store_data_shape(Shape *shape, void *data)
{
DataType type = UNKNOWN;
if (data) {
type = get_node_type(data);
switch (type) {
case POINT_SET:
shape->point_set = (PointSet *)data;
break;
case INDEXED_LINE_SET:
break;
case INDEXED_FACE_SET:
break;
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void *read_shape(void *args)
{
cout << "Hello Shape" << endl;
Shape *shape = NULL;
Container *container = NULL;
string tokn = "";
void *data = NULL;
int def_flag = 0;
string def_tokn = "";
shape = new_shape();
container = new_container();
if (gvar->def_flag) {
add_to_def(gvar->def_tokn, container);
}
if (shape) {
while (tokn.find("}") == string::npos) {
//------------------------------
// (1) Thelw mia sinattisi pou na tsimpaei apo to def map to swsto data
// (2) Apo to data tha tsimpaei to type
// (3) Apo to type tha apofasizei pou tha to apothikevei -> store_data_shape() prepei na volevei kai edw
// (4) break gia na stamatisei i while, gia auto den eimai poly sigouros, mallon den xriazetai
// giati mporei na exeis kai alla pedia
//
// opote ta data exoun apothikeutei mia xara... elpizw
if (gvar->use_flag) {
data = (*gvar->def_map2)[gvar->use_tokn];
store_data_shape(shape, data);
}
//------------------------------
if (gvar->def_flag) {
def_flag = 1;
def_tokn = gvar->def_tokn;
}
data = NULL;
tokn = get_tokn();
data = call_node_read_function(tokn, NULL);
store_data_shape(shape, data);
if (def_flag && data !=NULL) {
add_to_def_map(def_tokn, data);
}
}
//set_node_type(shape, SHAPE);
}
//debug_read_shape(shape);
return shape;
}
/*************************************************************************************/
/* Transform */
/*************************************************************************************/
Transform *new_transform()
{
Transform *transform = NULL;
transform = new Transform;
if (transform) {
transform->info = new Info;
transform->children = NULL;
}
return transform;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_transform(Transform *transform)
{
delete transform;
}
/*************************************************************************************/
/*************************************************************************************/
void *read_translation(void *args)
{
string tokn = "";
int valid_flag = 1;
double tmp;
int i = 0;
double *translation = NULL;
Transform *transform = NULL;
transform = (Transform *)args;
if (transform) {
translation = transform->translation;
}
if (translation) {
for (i = 0; i < 3; ++i) {
tokn = get_token();
if (is_number(tokn)) {
tmp = str2double(tokn, &valid_flag);
if (valid_flag) {
translation[i] = tmp;
}
}
}
}
return translation;
}
/*************************************************************************************/
/*************************************************************************************/
void *read_scale(void *args)
{
string tokn = "";
int valid_flag = 1;
double tmp;
int i = 0;
double *scale = NULL;
Transform *transform = NULL;
transform = (Transform *)args;
if (transform) {
scale = transform->rotation;
}
if (scale) {
for (i = 0; i < 3; ++i) {
tokn = get_token();
if (is_number(tokn)) {
tmp = str2double(tokn, &valid_flag);
if (valid_flag) {
scale[i] = tmp;
}
}
}
}
return scale;
}
/*************************************************************************************/
/*************************************************************************************/
void *read_rotation(void *args)
{
string tokn = "";
int valid_flag = 1;
double tmp;
int i = 0;
double *rotation = NULL;
Transform *transform = NULL;
transform = (Transform *)args;
if (transform) {
rotation = transform->rotation;
}
if (rotation) {
for (i = 0; i < 4; ++i) {
tokn = get_token();
if (is_number(tokn)) {
tmp = str2double(tokn, &valid_flag);
if (valid_flag) {
rotation[i] = tmp;
}
}
}
}
return rotation;
}
/*************************************************************************************/
/*************************************************************************************/
void debug_read_transform(void *args)
{
void *data = NULL;
int i = 0;
data = args;
if (data) {
if (get_node_type(data) == SHAPE) {
debug_read_shape(data);
} else if (get_node_type(data) == TRANSFORM) {
Transform *transform = (Transform *)data;
if (transform) {
for (i = 0; i < 3; i++) {
cout << "translation[" << i << "] -> " << transform->translation[i] << endl;
}
for (i = 0; i < 3; i++) {
cout << "scale[" << i << "] -> " << transform->scale[i] << endl;
}
for (i = 0; i < 4; i++) {
cout << "rotation[" << i << "] -> " << transform->rotation[i] << endl;
}
}
data = transform->children;
debug_read_transform(data);
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void store_data_transform(Transform *transform, void *data)
{
DataType type = UNKNOWN;
if (data) {
type = get_node_type(data);
switch (type) {
case SHAPE:
transform->children = data;
break;
case TRANSFORM:
transform->children = data;
break;
case GROUP:
transform->children = data;
break;
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void *read_transform(void *args)
{
cout << "Hello Transform" << endl;
Transform *transform = NULL;
string tokn = "";
void *data = NULL;
int def_flag = 0;
string def_tokn = "";
transform = new_transform();
if (transform) {
while (tokn.find("children") == string::npos && tokn.find("}") == string::npos) {
data = NULL;
tokn = get_tokn();
data = call_field_read_function(tokn, transform);
}
if (tokn.find("children") != string::npos) {
while(tokn.find("]") == string::npos) {
if (gvar->def_flag) {
def_flag = 1;
def_tokn = gvar->def_tokn;
}
data = NULL;
tokn = get_tokn();
data = call_node_read_function(tokn, NULL);
store_data_transform(transform, data);
if (def_flag && data !=NULL) {
add_to_def_map(def_tokn, data);
}
}
}
}
set_node_type(transform, TRANSFORM);
//debug_read_transform(transform);
return transform;
}
/*************************************************************************************/
/* Group */
/*************************************************************************************/
Group *new_group()
{
Group *group = NULL;
group = new Group;
if (group) {
group->children = NULL;
}
return group;
}
/*************************************************************************************/
/*************************************************************************************/
void delete_group(Group *group)
{
delete group;
}
/*************************************************************************************/
/*************************************************************************************/
#ifndef DATA_TYPES_H
#define DATA_TYPES_H
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef enum DataType {
UNKNOWN = 0,
SHAPE = 1,
COORDINATE,
INDEXED_LINE_SET,
INDEXED_FACE_SET,
TRANSFORM,
MATERIAL,
POINT_SET,
GROUP,
APPEARANCE,
ROTATION,
TRANSLATION,
SCALE,
POINT
} DataType;
typedef struct Container {
DataType type;
void *data;
} Container;
typedef struct Info {
int id;
DataType type;
} Id;
typedef struct Point {
struct Info *info;
double x;
double y;
double z;
} Point;
typedef struct CoordIndex {
struct Info *info;
vector<int> *coord_index_vec;
} CoordIndex;
typedef struct Coordinate {
struct Info *info;
vector<Point *> *coordinate_vec;
} Coord;
typedef struct IndexedLineSet {
struct Info *info;
Coordinate *coordinate;
vector<CoordIndex *> *indexed_line_set_vec;
} IndexedLineSet;
typedef struct IndexedFaceSet {
struct Info *info;
Coordinate *coordinate;
vector<CoordIndex *> *indexed_face_set_vec;
} IndexedFaceSet;
typedef struct Material {
struct Info *info;
double diffuse_color[3];
}Material;
typedef struct PointSet {
struct Info *info;
Coordinate *coordinate;
} Pointset;
typedef struct Appearance {
struct Info *info;
Material *material;
} Appearance;
typedef struct Shape {
struct Info *info;
Appearance *appearance;
Pointset *point_set;
IndexedLineSet *indexed_line_set;
IndexedFaceSet *indexed_face_set;
} Shape;
typedef struct Transform {
struct Info *info;
double translation[3];
double rotation[4];
double scale[3];
void *children;
} Transform;
typedef struct Group {
struct Info *info;
double b_boc_center[3];
double b_box_size[3];
void *children;
} Group;
typedef void *(*READ_NODE_FUN)(void *args);
typedef void *(*CREATE_FUN)(void *args);
typedef void *(*READ_FIELD_FUN)(void *args);
typedef struct DataSup {
string keyword;
DataType type;
READ_NODE_FUN read_node_fun;
READ_FIELD_FUN read_field_fun;
CREATE_FUN create_fun;
} DataSup;
/* FORWARD DECLARATION */
void init_node_type_map(map<string, DataType> **data_map);
void init_field_type_map(map<string, DataType> **data_map);
void init_type_sup_map(map<DataType, DataSup *> **data_sup_map);
void init_frame(vector<Container *> **frame);
void *read_coordinate(void *data);
void *read_point_set(void *data);
void *read_shape(void *data);
void *read_transform(void *data);
DataType get_container_type(Container *container);
void *get_container_data(Container *container);
void init_def(map<string, Container *> **def);
void check_def_tokn(string tokn);
void check_use_tokn(string tokn);
void add_to_def(string tokn, Container *container);
void* get_from_def(string tokn);
void check_def_use_tokn(string tokn);
void *read_point(void *args);
void *read_translation(void *args);
void *read_rotation(void *args);
void *read_scale(void *args);
int get_node_id(void *node);
DataType get_node_type(void *node);
void init_def_map2(map<string, void *> **def_map2);
void add_to_def_map(string tokn, void *data);
#endif // DATA_TYPES_H
#include "file_handler.h"
using namespace std;
vector<string> *token_stack = NULL;
ifstream *fp = NULL;
void init_token_stack()
{
if (token_stack == NULL) {
token_stack = new vector<string>;
}
}
void close_file(ifstream *fp)
{
fp->close();
}
ifstream *open_file(string file_name)
{
fp = new ifstream();
fp->open(file_name.c_str());
if (fp->is_open()) {
init_token_stack();
return fp;
} else {
cout << "Unable to open file" << endl;
close_file(fp);
return NULL;
}
}
void empty_token_stack()
{
// opote adeiazei to stack to programma paei kai tsimpaei nea grammi
// apo to arxeio
token_stack->erase(token_stack->begin(), token_stack->end());
}
void trim(string *s)
{
size_t p = s->find_first_not_of(" \t");
s->erase(0, p);
p = s->find_last_not_of(" \t");
if (string::npos != p)
s->erase(p+1);
}
string *read_line(string *line)
{
if (fp->good()) {
getline(*fp, *line);
trim(line);
//cout << "line: " << *line << endl;
} else {
line->clear();
}
return line;
}
void go_to_next_line()
{
empty_token_stack();
}
int is_blank(string token)
{
size_t value = 0;
if (token.find_first_not_of("\t\n ") == string::npos) {
//string is blank
value = 1;
}
return value;
}
void tokenize_line(string line)
{
size_t next = 0;
size_t prev = 0;
string delimiter = " ";
string substring;
while ((next = line.find_first_of(delimiter, prev)) != string::npos) {
if (next - prev != 0) {
substring = line.substr(prev, next - prev);
if (!is_blank(substring)) {
token_stack->push_back(substring);
}
}
prev = next + 1;
}
if (prev < line.size()) {
substring = line.substr(prev);
if (!is_blank(substring)) {
token_stack->push_back(substring);
}
}
}
string get_token()
{
string value, line;
if (!token_stack->empty()) {
value = token_stack->front();
token_stack->erase(token_stack->begin());
} else {
read_line(&line);
if (line.size() != 0) {
tokenize_line(line);
value = token_stack->front();
token_stack->erase(token_stack->begin());
}
}
//cout << "tokn: " << value << endl;
return value;
}
#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
ifstream *open_file(string file_name);
string get_token();
void go_to_next_line();
#endif // FILE_HANDLER_H
import random
import string
from typing import BinaryIO
def generate_random_input(out: BinaryIO):
# Generate a random number of nodes (between 1 and 10)
num_nodes = random.randint(1, 10)
out.write("#VRML V2.0 utf8\n".encode())
for _ in range(num_nodes):
# Randomly select a node type
node_type = random.choice(["Shape", "Transform", "PointSet"])
if node_type == "Shape":
out.write(f"Shape {{\n".encode())
# Generate random fields for Shape node
if random.random() < 0.5:
out.write("appearance Appearance {\n".encode())
out.write("material Material {\n".encode())
out.write(f"diffuseColor {random.random()} {random.random()} {random.random()}\n".encode())
out.write("}\n".encode())
out.write("}\n".encode())
geometry_type = random.choice(["PointSet", "IndexedLineSet", "IndexedFaceSet"])
out.write(f"geometry {geometry_type} {{\n".encode())
if geometry_type == "PointSet":
num_points = random.randint(1, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
elif geometry_type == "IndexedLineSet":
num_points = random.randint(2, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("coordIndex [\n".encode())
for i in range(num_points - 1):
out.write(f"{i}, {i+1}, -1,\n".encode())
out.write("]\n".encode())
elif geometry_type == "IndexedFaceSet":
num_points = random.randint(3, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("coordIndex [\n".encode())
indices = list(range(num_points))
random.shuffle(indices)
for i in range(0, num_points, 3):
out.write(f"{indices[i]}, {indices[i+1]}, {indices[i+2]}, -1,\n".encode())
out.write("]\n".encode())
out.write("}\n".encode()) # Close geometry
out.write("}\n".encode()) # Close Shape
elif node_type == "Transform":
out.write(f"Transform {{\n".encode())
# Generate random fields for Transform node
if random.random() < 0.5:
out.write(f"translation {random.random()} {random.random()} {random.random()}\n".encode())
if random.random() < 0.5:
out.write(f"rotation {random.random()} {random.random()} {random.random()} {random.random()}\n".encode())
if random.random() < 0.5:
out.write(f"scale {random.random()} {random.random()} {random.random()}\n".encode())
# Recursively generate children nodes
num_children = random.randint(0, 3)
if num_children > 0:
out.write("children [\n".encode())
for _ in range(num_children):
generate_random_input(out)
out.write("]\n".encode())
out.write("}\n".encode()) # Close Transform
elif node_type == "PointSet":
out.write(f"PointSet {{\n".encode())
num_points = random.randint(1, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("}\n".encode()) # Close PointSet
# Optionally add DEF/USE statements
if random.random() < 0.3:
def_name = ''.join(random.choices(string.ascii_letters, k=8))
out.write(f"DEF {def_name} ".encode())
generate_random_input(out)
if random.random() < 0.5:
out.write(f"USE {def_name}\n".encode())
# Example usage
with open("random.wrl", "wb") as file:
generate_random_input(file)
import random
import string
from typing import BinaryIO
def generate_random_input(out: BinaryIO):
# Generate a random number of nodes (between 1 and 10)
num_nodes = random.randint(1, 10)
out.write("#VRML V2.0 utf8\n".encode())
for _ in range(num_nodes):
# Randomly select a node type
node_type = random.choice(["Shape", "Transform", "PointSet"])
if node_type == "Shape":
out.write(f"Shape {{\n".encode())
# Generate random fields for Shape node
if random.random() < 0.5:
out.write("appearance Appearance {\n".encode())
out.write("material Material {\n".encode())
out.write(f"diffuseColor {random.random()} {random.random()} {random.random()}\n".encode())
out.write("}\n".encode())
out.write("}\n".encode())
geometry_type = random.choice(["PointSet", "IndexedLineSet", "IndexedFaceSet"])
out.write(f"geometry {geometry_type} {{\n".encode())
if geometry_type == "PointSet":
num_points = random.randint(1, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
elif geometry_type == "IndexedLineSet":
num_points = random.randint(2, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("coordIndex [\n".encode())
for i in range(num_points - 1):
out.write(f"{i}, {i+1}, -1,\n".encode())
out.write("]\n".encode())
elif geometry_type == "IndexedFaceSet":
num_points = random.randint(3, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("coordIndex [\n".encode())
indices = list(range(num_points))
random.shuffle(indices)
for i in range(0, num_points - 2, 3):
out.write(f"{indices[i]}, {indices[i+1]}, {indices[i+2]}, -1,\n".encode())
out.write("]\n".encode())
out.write("}\n".encode()) # Close geometry
out.write("}\n".encode()) # Close Shape
elif node_type == "Transform":
out.write(f"Transform {{\n".encode())
# Generate random fields for Transform node
if random.random() < 0.5:
out.write(f"translation {random.random()} {random.random()} {random.random()}\n".encode())
if random.random() < 0.5:
out.write(f"rotation {random.random()} {random.random()} {random.random()} {random.random()}\n".encode())
if random.random() < 0.5:
out.write(f"scale {random.random()} {random.random()} {random.random()}\n".encode())
# Recursively generate children nodes
num_children = random.randint(0, 3)
if num_children > 0:
out.write("children [\n".encode())
for _ in range(num_children):
generate_random_input(out)
out.write("]\n".encode())
out.write("}\n".encode()) # Close Transform
elif node_type == "PointSet":
out.write(f"PointSet {{\n".encode())
num_points = random.randint(1, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("}\n".encode()) # Close PointSet
# Optionally add DEF/USE statements
if random.random() < 0.3:
def_name = ''.join(random.choices(string.ascii_letters, k=8))
out.write(f"DEF {def_name} ".encode())
generate_random_input(out)
if random.random() < 0.5:
out.write(f"USE {def_name}\n".encode())
# Example usage
with open("random.wrl", "wb") as file:
generate_random_input(file)
import random
import string
from typing import BinaryIO
def generate_random_input(out: BinaryIO, max_depth: int = 5, current_depth: int = 0):
if current_depth >= max_depth:
return
# Generate a random number of nodes (between 1 and 5)
num_nodes = random.randint(1, 5)
if current_depth == 0:
out.write("#VRML V2.0 utf8\n".encode())
for _ in range(num_nodes):
# Randomly select a node type
node_type = random.choice(["Shape", "Transform", "PointSet"])
if node_type == "Shape":
out.write(f"Shape {{\n".encode())
# Generate random fields for Shape node
if random.random() < 0.5:
out.write("appearance Appearance {\n".encode())
out.write("material Material {\n".encode())
out.write(f"diffuseColor {random.random()} {random.random()} {random.random()}\n".encode())
out.write("}\n".encode())
out.write("}\n".encode())
geometry_type = random.choice(["PointSet", "IndexedLineSet", "IndexedFaceSet"])
out.write(f"geometry {geometry_type} {{\n".encode())
if geometry_type == "PointSet":
num_points = random.randint(1, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
elif geometry_type == "IndexedLineSet":
num_points = random.randint(2, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("coordIndex [\n".encode())
for i in range(num_points - 1):
out.write(f"{i}, {i+1}, -1,\n".encode())
out.write("]\n".encode())
elif geometry_type == "IndexedFaceSet":
num_points = random.randint(3, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("coordIndex [\n".encode())
indices = list(range(num_points))
random.shuffle(indices)
for i in range(0, num_points - 2, 3):
out.write(f"{indices[i]}, {indices[i+1]}, {indices[i+2]}, -1,\n".encode())
out.write("]\n".encode())
out.write("}\n".encode()) # Close geometry
out.write("}\n".encode()) # Close Shape
elif node_type == "Transform":
out.write(f"Transform {{\n".encode())
# Generate random fields for Transform node
if random.random() < 0.5:
out.write(f"translation {random.random()} {random.random()} {random.random()}\n".encode())
if random.random() < 0.5:
out.write(f"rotation {random.random()} {random.random()} {random.random()} {random.random()}\n".encode())
if random.random() < 0.5:
out.write(f"scale {random.random()} {random.random()} {random.random()}\n".encode())
# Recursively generate children nodes
num_children = random.randint(0, 3)
if num_children > 0:
out.write("children [\n".encode())
for _ in range(num_children):
generate_random_input(out, max_depth, current_depth + 1)
out.write("]\n".encode())
out.write("}\n".encode()) # Close Transform
elif node_type == "PointSet":
out.write(f"PointSet {{\n".encode())
num_points = random.randint(1, 10)
out.write("coord Coordinate {\n".encode())
out.write("point [\n".encode())
for _ in range(num_points):
out.write(f"{random.random()} {random.random()} {random.random()},\n".encode())
out.write("]\n".encode())
out.write("}\n".encode())
out.write("}\n".encode()) # Close PointSet
# Optionally add DEF/USE statements
if random.random() < 0.3:
def_name = ''.join(random.choices(string.ascii_letters, k=8))
out.write(f"DEF {def_name} ".encode())
generate_random_input(out, max_depth, current_depth + 1)
if random.random() < 0.5:
out.write(f"USE {def_name}\n".encode())
# Example usage
with open("random.wrl", "wb") as file:
generate_random_input(file)
#include <iostream>
#include "vrml_parser.h"
using namespace std;
int main(int argc, char **argv)
{
if (argc != 2) {
cerr << "usage: " << argv[0] << " <filename>" << endl;
return 1;
}
read_vrml(argv[1]);
return 0;
}
#include "str_and_math.h"
using namespace std;
int is_number(string s)
{
string::const_iterator it = s.begin();
while (it != s.end() && ( isdigit(*it) || *it == '.' || *it == '-')) {
++it;
}
return !s.empty() && it == s.end();
}
double str2double(string str, int *valid_flag)
{
char *endptr = NULL;
double value = strtod(str.c_str(), &endptr);
if (*endptr) {
*valid_flag = 0;
}
return value;
}
int find_comma_and_remove_it(string *tokn)
{
int pos = 0;
int value = 0;
if ( (pos = tokn->find_first_of(",")) != string::npos) {
*tokn = tokn->substr(0, pos);
value = 1;
}
return value;
}
#ifndef STR_AND_MATH_H
#define STR_AND_MATH_H
#include <string>
#include <cstdlib>
using namespace std;
int is_number(string s);
double str2double(string str, int *valid_flag);
int find_comma_and_remove_it(string *tokn);
#endif // STR_AND_MATH_H
#include "vrml_parser.h"
GlobalVar *gvar = NULL;
/*************************************************************************************/
/*************************************************************************************/
void init_gvar(map<string, DataType> *node_type_map, map<DataType, DataSup *> *type_sup_map,
map<string, DataType> *field_type_map, stack<string> *file_stack,
map<string, Container *> *def_map, map<string, void *> *def_map2)
{
if (gvar == NULL) {
gvar = new GlobalVar;
}
gvar->node_type_map = node_type_map;
gvar->type_sup_map = type_sup_map;
gvar->field_type_map = field_type_map;
gvar->file_stack = file_stack;
gvar->def_map = def_map;
gvar->def_map2 = def_map2;
gvar->frame = NULL;
gvar->def_flag = 0;
gvar->use_flag = 0;
gvar->def_tokn = "";
gvar->use_tokn = "";
}
/*************************************************************************************/
/*************************************************************************************/
map<string, DataType> *get_node_type_map()
{
return gvar->node_type_map;
}
/*************************************************************************************/
/*************************************************************************************/
map<DataType, DataSup *> *get_type_sup_map()
{
return gvar->type_sup_map;
}
/*************************************************************************************/
/*************************************************************************************/
map<string, Container *> *get_def_map()
{
return gvar->def_map;
}
/*************************************************************************************/
/*************************************************************************************/
map<string, DataType> *get_field_type_map()
{
return gvar->field_type_map;
}
/*************************************************************************************/
/* Stack */
/*************************************************************************************/
void init_stack(stack<string> **file_stack)
{
if (*file_stack == NULL) {
*file_stack = new stack<string>;
}
}
/*************************************************************************************/
/*************************************************************************************/
int check_tokn_to_add_stack(string tokn)
{
int value = 0;
map<string, DataType> *node_type_map = NULL;
map<string, DataType>::iterator node_type_map_it;
node_type_map = gvar->node_type_map;
node_type_map_it = node_type_map->find(tokn);
if (node_type_map) {
if (tokn.find("{") != string::npos) {
value = 1;
} else if (tokn.find("}") != string::npos) {
value = 1;
} else if (node_type_map_it != node_type_map->end()) {
value = 1;
}
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
string top_stack()
{
stack<string> *file_stack = NULL;
file_stack = gvar->file_stack;
string value;
if (file_stack) {
value = file_stack->top();
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
int check_matching_bracket(string tokn)
{
int value = 0;
if (top_stack() == "{" && tokn == "}") {
value = 1;
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
int top_is_bracket()
{
int value = 0;
string top;
top = top_stack();
if (top == "}" || top == "{") {
value = 1;
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
int size_stack()
{
stack<string> *file_stack = NULL;
file_stack = gvar->file_stack;
int value = 0;
if (file_stack) {
value = file_stack->size();
}
return value;
}
/*************************************************************************************/
/*************************************************************************************/
void push_stack(string tokn)
{
stack<string> *file_stack = NULL;
file_stack = gvar->file_stack;
string value;
if (file_stack) {
file_stack->push(tokn);
}
}
/*************************************************************************************/
/*************************************************************************************/
void pop_stack()
{
stack<string> *file_stack = NULL;
file_stack = gvar->file_stack;
string value;
if (file_stack) {
file_stack->pop();
}
}
/*************************************************************************************/
/*************************************************************************************/
void perform_stack_operations(string tokn)
{
if (check_tokn_to_add_stack(tokn)) {
if (size_stack()) {
if (check_matching_bracket(tokn)) {
// pop brackets
pop_stack();
if (!top_is_bracket()) {
//pop keyword
pop_stack();
}
} else {
push_stack(tokn);
}
} else {
push_stack(tokn);
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void stack_operations(string tokn)
{
perform_stack_operations(tokn);
}
/*************************************************************************************/
/*************************************************************************************/
void debug_stack(string msg)
{
cout << msg <<endl;
while (size_stack()) {
cout << " stack: "<<top_stack() << endl;
pop_stack();
}
}
/*************************************************************************************/
/*************************************************************************************/
string get_tokn()
{
string tokn;
//tokn = get_token();
//stack_operations(tokn);
tokn = get_token();
stack_operations(tokn);
// for comments inline
while (tokn.find_first_of("#") != string::npos) {
go_to_next_line();
tokn = get_token();
stack_operations(tokn);
}
check_def_tokn(tokn);
check_use_tokn(tokn);
return tokn;
}
/*************************************************************************************/
/*************************************************************************************/
void check_shape(Container *container)
{
PointSet *point_set = NULL;
Coordinate *coordinate = NULL;
vector<Point *> *coordinate_vec = NULL;
vector<Point *>::iterator it;
Point *point = NULL;
Shape *shape = NULL;
shape = (Shape *) get_container_data(container);
if (shape) {
point_set = shape->point_set;
if (point_set) {
coordinate = point_set->coordinate;
if (coordinate) {
coordinate_vec = coordinate->coordinate_vec;
if (coordinate_vec) {
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "r_shape value: x = " << point->x << " y = " << point->y << " z = "
<< point->z << endl;
}
}
}
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void check_read_point_set(void *args)
{
Coordinate *coordinate = NULL;
vector<Point *> *coordinate_vec = NULL;
vector<Point *>::iterator it;
Point *point = NULL;
PointSet *point_set = NULL;
point_set = (PointSet *)args;
if (point_set) {
coordinate = point_set->coordinate;
if (coordinate) {
coordinate_vec = coordinate->coordinate_vec;
if (coordinate_vec) {
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "r_point_set value: x = " << point->x << " y = " << point->y << " z = " << point->z << endl;
}
}
}
}
}
void check_shape2(void *args)
{
PointSet *point_set = NULL;
Coordinate *coordinate = NULL;
vector<Point *> *coordinate_vec = NULL;
vector<Point *>::iterator it;
Point *point = NULL;
Shape *shape = NULL;
shape = (Shape *)args;
if (shape) {
point_set = shape->point_set;
if (point_set) {
coordinate = point_set->coordinate;
if (coordinate) {
coordinate_vec = coordinate->coordinate_vec;
if (coordinate_vec) {
for (it = coordinate_vec->begin(); it != coordinate_vec->end(); ++it) {
point = *it;
if (point)
cout << "r_shape value: x = " << point->x << " y = " << point->y << " z = "
<< point->z << endl;
}
}
}
}
}
}
void check_transform2(void *args)
{
int i;
DataType type;
void *data = NULL;
data = args;
if (data) {
while (data != NULL) {
type = get_node_type(data);
if (type == SHAPE) {
check_shape2(data);
data = NULL;
} else if ( type == TRANSFORM) {
Transform *transform = (Transform *)data;
for (i = 0; i < 3; i++) {
cout << "translation[" << i << "] -> " << transform->translation[i] << endl;
}
for (i = 0; i < 3; i++) {
cout << "scale[" << i << "] -> " << transform->scale[i] << endl;
}
for (i = 0; i < 4; i++) {
cout << "rotation[" << i << "] -> " << transform->rotation[i] << endl;
}
data = transform->children;
} else {
data = NULL;
}
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void check_frame(vector<Container *> *frame)
{
vector<Container *>::iterator it;
DataType type = UNKNOWN;
for (it = frame->begin(); it != frame->end(); ++it) {
type = get_container_type((Container *)*it);
if (type == SHAPE) {
cout << "SHAPE" << endl;
check_shape(*it);
} else if (type == TRANSFORM) {
//check_transform(*it);
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void debug_def2()
{
map<string, void *>::iterator def_map_it;
map<string, void *> *def_map = NULL;
def_map = gvar->def_map2;
int i = 0;
if (def_map) {
for (def_map_it = def_map->begin(); def_map_it != def_map->end(); ++def_map_it) {
cout << "def map key: " << def_map_it->first <<" value: " << def_map_it->second << endl;
i++;
if (i == 1) {
cout << endl << "@@@@@@@@@@ TRANSFORM @@@@@@@@@@@" << endl;
check_transform2(def_map_it->second);
}
if (i == 2) {
cout << endl << "@@@@@@@@@@ SHAPE @@@@@@@@@@@" << endl;
check_shape2(def_map_it->second);
}
if (i == 3) {
cout << endl << "@@@@@@@@@@ POINTSET @@@@@@@@@@@" << endl;
check_read_point_set(def_map_it->second);
}
}
}
}
/*************************************************************************************/
/*************************************************************************************/
void *call_node_read_function(string tokn, void *args)
{
map<string, DataType> *node_type_map = NULL;
map<string, DataType>::iterator node_type_map_it;
map<DataType, DataSup *> *type_sup_map = NULL;
map<DataType, DataSup *>::iterator type_sup_map_it;
void *data = NULL;
node_type_map = get_node_type_map();
type_sup_map = get_type_sup_map();
node_type_map_it = node_type_map->find(tokn);
if (node_type_map_it != node_type_map->end()) {
type_sup_map_it = type_sup_map->find(node_type_map_it->second);
if (type_sup_map_it != type_sup_map->end()) {
data = type_sup_map_it->second->read_node_fun(args);
}
}
return data;
}
/*************************************************************************************/
/*************************************************************************************/
void *call_field_read_function(string tokn, void *args)
{
map<string, DataType> *field_type_map = NULL;
map<string, DataType>::iterator field_type_map_it;
map<DataType, DataSup *> *type_sup_map = NULL;
map<DataType, DataSup *>::iterator type_sup_map_it;
void *data = NULL;
field_type_map = get_field_type_map();
type_sup_map = get_type_sup_map();
field_type_map_it = field_type_map->find(tokn);
if (field_type_map_it != field_type_map->end()) {
type_sup_map_it = type_sup_map->find(field_type_map_it->second);
if (type_sup_map_it != type_sup_map->end()) {
data = type_sup_map_it->second->read_field_fun(args);
}
}
return data;
}
/*************************************************************************************/
/*************************************************************************************/
void read_vrml(char *filename)
{
string tokn;
ifstream *fp = NULL;
map<string, DataType> *node_type_map = NULL;
map<DataType, DataSup *> *type_sup_map = NULL;
map<string, DataType> *field_type_map = NULL;
stack<string> *file_stack = NULL;
vector<Container *> *frame = NULL;
map<string, Container *> *def = NULL;
map<string, void *> *def_map2 = NULL;
void *data = NULL;
DataType data_type = UNKNOWN;
init_node_type_map(&node_type_map);
init_field_type_map(&field_type_map);
init_type_sup_map(&type_sup_map);
init_stack(&file_stack);
init_frame(&frame);
init_def(&def);
init_def_map2(&def_map2);
init_gvar(node_type_map, type_sup_map, field_type_map, file_stack, def, def_map2);
gvar->frame = frame;
int i = 0;
int def_flag = 0;
string def_tokn;
//fp = open_file("/home/alepapadop/VRML/5pointset.wrl");
//fp = open_file("/home/alepapadop/VRML/a.wrl");
fp = open_file(filename);
while (fp->good()) {
tokn = get_tokn();
if (gvar->def_flag) {
def_flag = 1;
def_tokn = gvar->def_tokn;
//gvar->def_flag = 0;
//gvar->def_tokn = "";
}
data = call_node_read_function(tokn, NULL);
if (def_flag && data !=NULL) {
add_to_def(def_tokn, (Container *)data);
add_to_def_map(def_tokn, data);
//(*(gvar->def_map2))[def_tokn] = data;
}
if (data != NULL) {
frame->push_back((Container *)data);
}
data = NULL;
// lthos auto, edw einai pou tha mpainei sto file data to frame
if (!size_stack()) {
init_frame(&frame);
gvar->frame = frame;
}
data_type = UNKNOWN;
i ++;
if (i == 100) break;
}
check_frame(frame);
debug_stack("\nSTACK \n\n");
// debug_def();
debug_def2();
}
#ifndef VRML_PARSER_H
#define VRML_PARSER_H
#include <string>
#include <stack>
#include "file_handler.h"
#include "data_types.h"
using namespace std;
typedef struct GlobalVar {
map<string, DataType> *node_type_map;
map<DataType, DataSup *> *type_sup_map;
map<string, DataType> *field_type_map;
map<string, Container *> *def_map;
map<string, void *> *def_map2;
stack<string> *file_stack;
vector<Container *> *frame;
int def_flag;
int use_flag;
string def_tokn;
string use_tokn;
} GlobalVar;
void read_vrml(char *);
string get_tokn();
void *call_node_read_function(string tokn, void *args);
void *call_field_read_function(string tokn, void *args);
extern GlobalVar *gvar;
#endif // VRML_PARSER_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment