X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffileio.cpp;h=1002dca87fecf22b79cbb2883253e9660fe6c34b;hb=e78daf62eb771ee29a59035d16cf63c1e6ebe144;hp=4a1c25f1de1c47bffd33280697acb425789eafe7;hpb=676007c81e292079daaa7188f4fbf2757ae77ef8;p=architektonas diff --git a/src/fileio.cpp b/src/fileio.cpp index 4a1c25f..1002dca 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -8,21 +8,18 @@ // JLH = James Hammons // // Who When What -// --- ---------- ------------------------------------------------------------- +// --- ---------- ------------------------------------------------------------ // JLH 02/20/2013 Created this file // #include "fileio.h" //#include +#include #include #include #include -#include "arc.h" -#include "circle.h" -#include "container.h" -#include "dimension.h" -#include "line.h" +#include "structs.h" /* How to handle connected objects @@ -101,46 +98,65 @@ perpendicular, or an arbitrary angle. How to encode that information? It's not intrinsic to either the Line or the Circle, but is a function of the relationship between them by virtue of their connection. + +OTHER CONSIDERATIONS: +--------------------- + + - Need to figure out how to store the Layer list (should layer list be optional?) + - Need to figure out how to store the Block list and blocks + + */ -enum ObjectType { OTContainer, OTContainerEnd, OTLine, OTCircle, OTArc, OTDimension, - OTPolygon, OTText, OTImage, OTBlock, OTEndOfFile }; +//enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc, +// OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile }; +enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile }; + + +// Instantiate class variables +/*static*/ int FileIO::objectFileType = OTFObject; -/*static*/ bool FileIO::SaveAtnsFile(FILE * file, Container * object) +/*static*/ bool FileIO::SaveAtnsFile(FILE * file, Container * c) { - /* Approach: loop through the container, doing a depth-first traversal. Any extra - containers found are looped through until there aren't any more down, then - ordinary objects are described. This can be handled by a virtual Object function - that reports the object by itself if it's a non-Container, otherwise it - enumerates all objects within itself. */ - - fprintf(file, "ARCHITEKTONAS DRAWING V1.0\n"); -#if 1 + /* Approach: loop through the container, doing a depth-first traversal. Any + extra containers found are looped through until there aren't any more + down, then ordinary objects are described. This can be handled by a + virtual Object function that reports the object by itself if it's a non- + Container, otherwise it enumerates all objects within itself. */ + + fprintf(file, "ARCHITEKTONAS DRAWING V1.1\n"); +#if 0 object->Enumerate(file); - fprintf(file, "END\n"); - return true; #else - return false; + WriteObjectToFile(file, (Object *)c); #endif + fprintf(file, "END\n"); + return true; } /*static*/ bool FileIO::LoadAtnsFile(FILE * file, Container * drawing) { -// char buffer[256]; float version; fscanf(file, "ARCHITEKTONAS DRAWING V%f", &version); //printf("Load: version = %f\n", version); - if (version != 1.0) - return false; - /* Approach: read each object in the file, one by one. If the object is a Container, - add objects to it until an "endContainer" marker is found. This will require a - stack to maintain the current Container. */ +// if (version != 1.0) +// return false; + + if (version == 1.0) + return LoadVersion1_0(file, drawing); + else if (version == 1.1) + return LoadVersion1_1(file, drawing); + + return false; + /* Approach: read each object in the file, one by one. If the object is a + Container, add objects to it until an "endContainer" marker is found. + This will require a stack to maintain the current Container. */ -#if 1 +#if 0 std::vector containerStack; Container * currentTopContainer = drawing;//new Container(Vector(0, 0)); Object * object; @@ -153,21 +169,22 @@ enum ObjectType { OTContainer, OTContainerEnd, OTLine, OTCircle, OTArc, OTDimens return false; // object->type down below can be replaced with objType. - // Above could be: bool FileIO::GetObjectFromFile(FILE *, Object *, ObjectType *); - // where the return value tells if it's a valid object, Object * returns the - // reconstructed object and ObjectType * returns the object type. + // Above could be: bool FileIO::GetObjectFromFile(FILE *, Object *, + // ObjectType *); where the return value tells if it's a valid object, + // Object * returns the reconstructed object and ObjectType * returns + // the object type. - if (objectType == OTEndOfFile) + if (objectType == OTFEndOfFile) { -printf("Load: container size = %li\n", drawing->objects.size()); +//printf("Load: container size = %li\n", drawing->objects.size()); return true; } - else if (objectType == OTContainer) + else if (objectType == OTFContainer) { containerStack.push_back(currentTopContainer); currentTopContainer = new Container(Vector(0, 0), currentTopContainer); } - else if (objectType == OTContainerEnd) + else if (objectType == OTFContainerEnd) { Container * containerToAdd = currentTopContainer; currentTopContainer = containerStack.back(); @@ -177,7 +194,7 @@ printf("Load: container size = %li\n", drawing->objects.size()); else { currentTopContainer->Add(object); -printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size()); +//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size()); } } @@ -188,66 +205,246 @@ printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.siz } -/*static*/ bool FileIO::GetObjectFromFile(FILE * file, Object * parent, Object ** object, int * objectType) +/*static*/ bool FileIO::LoadVersion1_0(FILE * file, Container * drawing) +{ + // Approach: read each object in the file, one by one. If the object is a + // Container, add objects to it until an "endContainer" marker is found. + // This will require a stack to maintain the current Container. + std::vector containerStack; + Container * currentTopContainer = drawing; + + while (!feof(file)) + { + // Reconstruct the object + Object * obj = GetObjectFromFile(file); + + // objectFileType is set in GetObjectFromFile()... + if (objectFileType == OTFObject) + { + if (obj == NULL) + return false; + + currentTopContainer->objects.push_back(obj); +//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size()); + + // If the object is a container, push current TLC on the stack and + // set it as the new TLC + if (obj->type == OTContainer) + { + containerStack.push_back(currentTopContainer); + currentTopContainer = (Container *)obj; + } + } + else if (objectFileType == OTFContainerEnd) + { + // Container is done, so pop the stack to get back the previous TLC + currentTopContainer = containerStack.back(); + containerStack.pop_back(); + } + else if (objectFileType == OTFEndOfFile) + { +//printf("Load: container size = %li\n", drawing->objects.size()); + return true; + } + } + + return false; +} + + +/*static*/ bool FileIO::LoadVersion1_1(FILE * file, Container * drawing) +{ + // Approach: read each object in the file, one by one. If the object is a + // Container, add objects to it until an "endContainer" marker is found. + // This will require a stack to maintain the current Container. + std::vector containerStack; + Container * currentTopContainer = drawing; + + while (!feof(file)) + { + // Reconstruct the object (extended format!) + Object * obj = GetObjectFromFile(file, true); + + // objectFileType is set in GetObjectFromFile()... + if (objectFileType == OTFObject) + { + if (obj == NULL) + return false; + + currentTopContainer->objects.push_back(obj); +//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size()); + + // If the object is a container, push current TLC on the stack and + // set it as the new TLC + if (obj->type == OTContainer) + { + containerStack.push_back(currentTopContainer); + currentTopContainer = (Container *)obj; + } + } + else if (objectFileType == OTFContainerEnd) + { + // Container is done, so pop the stack to get back the previous TLC + currentTopContainer = containerStack.back(); + containerStack.pop_back(); + } + else if (objectFileType == OTFEndOfFile) + { +//printf("Load: container size = %li\n", drawing->objects.size()); + return true; + } + } + + return false; +} + + +/*static*/ Object * FileIO::GetObjectFromFile(FILE * file, bool extended/*= false*/) { char buffer[256]; - fscanf(file, "%s ", buffer); - bool recognized = false; -//printf("Load: buffer = \"%s\"\n", buffer); + int foundLayer = 0; + /*int num =*/ fscanf(file, "%s", buffer); + Object * obj = NULL; + objectFileType = OTFObject; +//printf("FileIO: fscanf returned %i, buffer = \"%s\"\n", num, buffer); + +// The following fugliness is for troubleshooting. Can remove later. + if ((strcmp(buffer, "END") != 0) && (strcmp(buffer, "ENDCONTAINER") != 0)) +{ +errno = 0; + /*num =*/ fscanf(file, " %i ", &foundLayer); +//printf("FileIO: fscanf returned %i, foundLayer = %i\n", num, foundLayer); +if (errno) +{ + if (errno == EAGAIN) + printf("EAGAIN\n"); + else if (errno == EBADF) + printf("EBADF\n"); + else if (errno == EILSEQ) + printf("EILSEQ\n"); + else if (errno == EINTR) + printf("EINTR\n"); + else if (errno == EINVAL) + printf("EINVAL\n"); + else if (errno == ENOMEM) + printf("ENOMEM\n"); + else if (errno == ERANGE) + printf("ERANGE\n"); + else + printf("errno = %i\n", errno); +} +} + // Need to add pen attributes as well... do that for v1.1 :-P if (strcmp(buffer, "LINE") == 0) { -//printf(" Found LINE.\n"); - recognized = true; - Vector v1, v2; - fscanf(file, "(%lf,%lf) (%lf,%lf)", &v1.x, &v1.y, &v2.x, &v2.y); -//printf(" Number of params recognized: %i\n", n); - *object = new Line(v1, v2, parent); - *objectType = OTLine; + Point p1, p2; + fscanf(file, "(%lf,%lf) (%lf,%lf)", &p1.x, &p1.y, &p2.x, &p2.y); + obj = (Object *)new Line(p1, p2); } else if (strcmp(buffer, "CIRCLE") == 0) { - recognized = true; - Vector v; + Point p; double r; - fscanf(file, "(%lf,%lf) %lf", &v.x, &v.y, &r); - *object = new Circle(v, r, parent); - *objectType = OTCircle; + fscanf(file, "(%lf,%lf) %lf", &p.x, &p.y, &r); + obj = (Object *)new Circle(p, r); } else if (strcmp(buffer, "ARC") == 0) { - recognized = true; - Vector v; + Point p; double r, a1, a2; - fscanf(file, "(%lf,%lf) %lf, %lf, %lf", &v.x, &v.y, &r, &a1, &a2); - *object = new Arc(v, r, a1, a2, parent); - *objectType = OTArc; + fscanf(file, "(%lf,%lf) %lf, %lf, %lf", &p.x, &p.y, &r, &a1, &a2); + obj = (Object *)new Arc(p, r, a1, a2); } else if (strcmp(buffer, "DIMENSION") == 0) { - recognized = true; - Vector v1, v2; + Point p1, p2; DimensionType type; - fscanf(file, "(%lf,%lf) (%lf,%lf) %i", &v1.x, &v1.y, &v2.x, &v2.y, &type); - *object = new Dimension(v1, v2, type, parent); - *objectType = OTDimension; + fscanf(file, "(%lf,%lf) (%lf,%lf) %i", &p1.x, &p1.y, &p2.x, &p2.y, (int *)&type); + obj = (Object *)new Dimension(p1, p2, type); } else if (strcmp(buffer, "CONTAINER") == 0) { - recognized = true; - *objectType = OTContainer; + obj = (Object *)new Container(); +// objectFileType = OTFContainer; } else if (strcmp(buffer, "ENDCONTAINER") == 0) { - recognized = true; - *objectType = OTContainerEnd; + objectFileType = OTFContainerEnd; } else if (strcmp(buffer, "END") == 0) { - recognized = true; - *objectType = OTEndOfFile; + objectFileType = OTFEndOfFile; + } + + if (obj != NULL) + { + obj->layer = foundLayer; + + if (extended && (obj->type != OTContainer)) + { + fscanf(file, " (%i, %f, %i)", &obj->color, &obj->thickness, &obj->style); + } } - return recognized; + return obj; +} + + +/*static*/ bool FileIO::WriteObjectToFile(FILE * file, Object * obj) +{ + // Sanity check + if (obj == NULL) + return false; + + switch (obj->type) + { + case OTLine: + fprintf(file, "LINE %i (%lf,%lf) (%lf,%lf)", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y); + break; + case OTCircle: + fprintf(file, "CIRCLE %i (%lf,%lf) %lf", obj->layer, obj->p[0].x, obj->p[0].y, obj->radius[0]); + break; + case OTEllipse: + break; + case OTArc: + fprintf(file, "ARC %i (%lf,%lf) %lf, %lf, %lf", obj->layer, obj->p[0].x, obj->p[0].y, obj->radius[0], obj->angle[0], obj->angle[1]); + break; + case OTPolygon: + break; + case OTDimension: +// fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, dimensionType); + fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y, ((Dimension *)obj)->subtype); + break; + case OTSpline: + break; + case OTText: + fprintf(file, "TEXT %i (%lf,%lf) \"%s\"", obj->layer, obj->p[0].x, obj->p[0].y, ((Text *)obj)->s.c_str()); + break; + case OTContainer: + { + Container * c = (Container *)obj; + + if (c->topLevel == false) + fprintf(file, "CONTAINER %i\n", obj->layer); + + std::vector::iterator i; + + for(i=c->objects.begin(); i!=c->objects.end(); i++) + WriteObjectToFile(file, (Object *)*i); + + if (c->topLevel == false) + fprintf(file, "ENDCONTAINER\n"); + + break; + } + default: + break; + } + + if (obj->type != OTContainer) + fprintf(file, " (%i, %f, %i)\n", obj->color, obj->thickness, obj->style); + + return true; }