diff --git a/spine-c/example/main.c b/spine-c/example/main.c index 928836e30..3f021f675 100644 --- a/spine-c/example/main.c +++ b/spine-c/example/main.c @@ -92,6 +92,12 @@ RegionAttachment* RegionAttachment_new (const char* name, AtlasRegion* region) { /**/ +char* _Util_readFile (const char* path, int* length) { + return _readFile(path, length); +} + +/**/ + int main (void) { Atlas* atlas = Atlas_readAtlasFile("data/spineboy.atlas"); printf("First region name: %s, x: %d, y: %d\n", atlas->regions->name, atlas->regions->x, atlas->regions->y); diff --git a/spine-c/include/spine/Atlas.h b/spine-c/include/spine/Atlas.h index 18c9f884e..a2eb99cab 100644 --- a/spine-c/include/spine/Atlas.h +++ b/spine-c/include/spine/Atlas.h @@ -90,7 +90,7 @@ typedef struct { AtlasRegion* regions; } Atlas; -Atlas* Atlas_readAtlas (const char* data); +Atlas* Atlas_readAtlas (const char* data, unsigned long length); Atlas* Atlas_readAtlasFile (const char* path); void Atlas_free (Atlas* atlas); diff --git a/spine-c/include/spine/Skeleton.h b/spine-c/include/spine/Skeleton.h index d819dd5b3..3a5eec20a 100644 --- a/spine-c/include/spine/Skeleton.h +++ b/spine-c/include/spine/Skeleton.h @@ -54,7 +54,6 @@ struct Skeleton { const void* const vtable; }; -Skeleton* Skeleton_new (SkeletonData* data); void Skeleton_free (Skeleton* skeleton); void Skeleton_updateWorldTransform (const Skeleton* skeleton); diff --git a/spine-c/include/spine/extension.h b/spine-c/include/spine/extension.h index 75e149e5e..0c97ee06f 100644 --- a/spine-c/include/spine/extension.h +++ b/spine-c/include/spine/extension.h @@ -76,7 +76,11 @@ /* Frees memory. Can be used on const. */ #define FREE(VALUE) free((void*)VALUE) +/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const. */ +#define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)malloc(strlen(FROM)), FROM) + #include +#include #include #include #include @@ -89,19 +93,21 @@ extern "C" { #endif /* - * Public API that must be implemented: + * Functions that must be implemented: */ -Skeleton* Skeleton_new (SkeletonData* data); - RegionAttachment* RegionAttachment_new (const char* name, AtlasRegion* region); AtlasPage* AtlasPage_new (const char* name); +char* _Util_readFile (const char* path, int* length); + /* * Internal API available for extension: */ +char* _readFile (const char* path, int* length); + typedef struct _SkeletonVtable { void (*free) (Skeleton* skeleton); } _SkeletonVtable; diff --git a/spine-c/src/spine/Animation.c b/spine-c/src/spine/Animation.c index 3ed218609..bb7b7bfeb 100644 --- a/spine-c/src/spine/Animation.c +++ b/spine-c/src/spine/Animation.c @@ -26,7 +26,6 @@ #include #include #include -#include Animation* Animation_new (int timelineCount) { Animation* self = NEW(Animation); diff --git a/spine-c/src/spine/Atlas.c b/spine-c/src/spine/Atlas.c index 5263e02f8..f13b4d336 100644 --- a/spine-c/src/spine/Atlas.c +++ b/spine-c/src/spine/Atlas.c @@ -26,7 +26,6 @@ #include #include #include -#include void _AtlasPage_init (AtlasPage* self, const char* name) { CONST_CAST(_AtlasPageVtable*, self->vtable) = NEW(_AtlasPageVtable); @@ -73,24 +72,24 @@ static void trim (Str* str) { } /* Tokenize string without modification. Returns 0 on failure. */ -static int readLine (const char* data, Str* str) { +static int readLine (const char* begin, const char* end, Str* str) { static const char* nextStart; - if (data) { - nextStart = data; + if (begin) { + nextStart = begin; return 1; } - if (*nextStart == '\0') return 0; + if (nextStart == end) return 0; str->begin = nextStart; /* Find next delimiter. */ do { nextStart++; - } while (*nextStart != '\0' && *nextStart != '\n'); + } while (nextStart != end && *nextStart != '\n'); str->end = nextStart; trim(str); - if (*nextStart != '\0') nextStart++; + if (nextStart != end) nextStart++; return 1; } @@ -108,17 +107,17 @@ static int beginPast (Str* str, char c) { } /* Returns 0 on failure. */ -static int readValue (Str* str) { - readLine(0, str); +static int readValue (const char* end, Str* str) { + readLine(0, end, str); if (!beginPast(str, ':')) return 0; trim(str); return 1; } /* Returns the number of tuple values read (2, 4, or 0 for failure). */ -static int readTuple (Str tuple[]) { +static int readTuple (const char* end, Str tuple[]) { Str str; - readLine(0, &str); + readLine(0, end, &str); if (!beginPast(&str, ':')) return 0; int i = 0; for (i = 0; i < 3; ++i) { @@ -160,7 +159,7 @@ static int toInt (Str* str) { return strtol(str->begin, (char**)&str->end, 10); } -static Atlas* abort (Atlas* self) { +static Atlas* abortAtlas (Atlas* self) { Atlas_free(self); return 0; } @@ -169,7 +168,9 @@ static const char* formatNames[] = {"Alpha", "Intensity", "LuminanceAlpha", "RGB static const char* textureFilterNames[] = {"Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", "MipMapNearestLinear", "MipMapLinearLinear"}; -Atlas* Atlas_readAtlas (const char* data) { +Atlas* Atlas_readAtlas (const char* begin, unsigned long length) { + const char* end = begin + length; + Atlas* self = NEW(Atlas); AtlasPage *page = 0; @@ -177,8 +178,8 @@ Atlas* Atlas_readAtlas (const char* data) { AtlasRegion *lastRegion = 0; Str str; Str tuple[4]; - readLine(data, 0); - while (readLine(0, &str)) { + readLine(begin, 0, 0); + while (readLine(0, end, &str)) { if (str.end - str.begin == 0) { page = 0; } else if (!page) { @@ -189,14 +190,14 @@ Atlas* Atlas_readAtlas (const char* data) { self->pages = page; lastPage = page; - if (!readValue(&str)) return abort(self); + if (!readValue(end, &str)) return abortAtlas(self); page->format = (AtlasFormat)indexOf(formatNames, 7, &str); - if (!readTuple(tuple)) return abort(self); + if (!readTuple(end, tuple)) return abortAtlas(self); page->minFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple); page->magFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple + 1); - if (!readValue(&str)) return abort(self); + if (!readValue(end, &str)) return abortAtlas(self); if (!equals(&str, "none")) { page->uWrap = *str.begin == 'x' ? ATLAS_REPEAT : (*str.begin == 'y' ? ATLAS_CLAMPTOEDGE : ATLAS_REPEAT); page->vWrap = *str.begin == 'x' ? ATLAS_CLAMPTOEDGE : (*str.begin == 'y' ? ATLAS_REPEAT : ATLAS_REPEAT); @@ -212,19 +213,19 @@ Atlas* Atlas_readAtlas (const char* data) { region->page = page; region->name = mallocString(&str); - if (!readValue(&str)) return abort(self); + if (!readValue(end, &str)) return abortAtlas(self); region->rotate = equals(&str, "true"); - if (readTuple(tuple) != 2) return abort(self); + if (readTuple(end, tuple) != 2) return abortAtlas(self); region->x = toInt(tuple); region->y = toInt(tuple + 1); - if (readTuple(tuple) != 2) return abort(self); + if (readTuple(end, tuple) != 2) return abortAtlas(self); region->width = toInt(tuple); region->height = toInt(tuple + 1); int count; - if (!(count = readTuple(tuple))) return abort(self); + if (!(count = readTuple(end, tuple))) return abortAtlas(self); if (count == 4) { /* split is optional */ region->splits = MALLOC(int, 4); region->splits[0] = toInt(tuple); @@ -232,7 +233,7 @@ Atlas* Atlas_readAtlas (const char* data) { region->splits[2] = toInt(tuple + 2); region->splits[3] = toInt(tuple + 3); - if (!(count = readTuple(tuple))) return abort(self); + if (!(count = readTuple(end, tuple))) return abortAtlas(self); if (count == 4) { /* pad is optional, but only present with splits */ region->pads = MALLOC(int, 4); region->pads[0] = toInt(tuple); @@ -240,18 +241,18 @@ Atlas* Atlas_readAtlas (const char* data) { region->pads[2] = toInt(tuple + 2); region->pads[3] = toInt(tuple + 3); - if (!readTuple(tuple)) return abort(self); + if (!readTuple(end, tuple)) return abortAtlas(self); } } region->originalWidth = toInt(tuple); region->originalHeight = toInt(tuple + 1); - readTuple(tuple); + readTuple(end, tuple); region->offsetX = (float)toInt(tuple); region->offsetY = (float)toInt(tuple + 1); - if (!readValue(&str)) return abort(self); + if (!readValue(end, &str)) return abortAtlas(self); region->index = toInt(&str); } } @@ -260,9 +261,10 @@ Atlas* Atlas_readAtlas (const char* data) { } Atlas* Atlas_readAtlasFile (const char* path) { - const char* data = readFile(path); + int length; + const char* data = _Util_readFile(path, &length); if (!data) return 0; - Atlas* atlas = Atlas_readAtlas(data); + Atlas* atlas = Atlas_readAtlas(data, length); FREE(data); return atlas; } diff --git a/spine-c/src/spine/AtlasAttachmentLoader.c b/spine-c/src/spine/AtlasAttachmentLoader.c index 4c8362578..49f16865e 100644 --- a/spine-c/src/spine/AtlasAttachmentLoader.c +++ b/spine-c/src/spine/AtlasAttachmentLoader.c @@ -26,7 +26,6 @@ #include #include #include -#include void _AtlasAttachmentLoader_free (AttachmentLoader* self) { _AttachmentLoader_deinit(self); diff --git a/spine-c/src/spine/Attachment.c b/spine-c/src/spine/Attachment.c index f2c835a9c..d17e7badb 100644 --- a/spine-c/src/spine/Attachment.c +++ b/spine-c/src/spine/Attachment.c @@ -25,7 +25,6 @@ #include #include -#include #include void _Attachment_init (Attachment* self, const char* name, AttachmentType type) { diff --git a/spine-c/src/spine/AttachmentLoader.c b/spine-c/src/spine/AttachmentLoader.c index 9a6e59ba4..3d9759333 100644 --- a/spine-c/src/spine/AttachmentLoader.c +++ b/spine-c/src/spine/AttachmentLoader.c @@ -25,7 +25,6 @@ #include #include -#include void _AttachmentLoader_init (AttachmentLoader* self) { CONST_CAST(_AttachmentLoaderVtable*, self->vtable) = NEW(_AttachmentLoaderVtable); diff --git a/spine-c/src/spine/BoneData.c b/spine-c/src/spine/BoneData.c index ea1732574..8dc3ac67d 100644 --- a/spine-c/src/spine/BoneData.c +++ b/spine-c/src/spine/BoneData.c @@ -25,7 +25,6 @@ #include #include -#include BoneData* BoneData_new (const char* name, BoneData* parent) { BoneData* self = NEW(BoneData); diff --git a/spine-c/src/spine/Json.c b/spine-c/src/spine/Json.c index cf74674ba..2cd7f92ed 100644 --- a/spine-c/src/spine/Json.c +++ b/spine-c/src/spine/Json.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include static const char* ep; diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c index ec2437e9c..ebc9ec585 100644 --- a/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/src/spine/SkeletonJson.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,8 @@ static float toColor (const char* value, int index) { } SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* self, const char* path) { - const char* json = readFile(path); + int length; + const char* json = _Util_readFile(path, &length); if (!json) { _SkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path); return 0; @@ -240,13 +240,14 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso } Animation* SkeletonJson_readAnimationFile (SkeletonJson* self, const char* path, const SkeletonData *skeletonData) { - const char* data = readFile(path); - if (!data) { + int length; + const char* json = _Util_readFile(path, &length); + if (!json) { _SkeletonJson_setError(self, 0, "Unable to read animation file: ", path); return 0; } - Animation* animation = SkeletonJson_readAnimation(self, data, skeletonData); - FREE(data); + Animation* animation = SkeletonJson_readAnimation(self, json, skeletonData); + FREE(json); return animation; } diff --git a/spine-c/src/spine/Skin.c b/spine-c/src/spine/Skin.c index c8d41485d..d44790726 100644 --- a/spine-c/src/spine/Skin.c +++ b/spine-c/src/spine/Skin.c @@ -25,7 +25,6 @@ #include #include -#include SkinEntry* _SkinEntry_new (int slotIndex, const char* name, Attachment* attachment) { SkinEntry* self = NEW(SkinEntry); diff --git a/spine-c/src/spine/SlotData.c b/spine-c/src/spine/SlotData.c index 5dc1ef827..bce6616f7 100644 --- a/spine-c/src/spine/SlotData.c +++ b/spine-c/src/spine/SlotData.c @@ -25,7 +25,6 @@ #include #include -#include SlotData* SlotData_new (const char* name, BoneData* boneData) { SlotData* self = NEW(SlotData); diff --git a/spine-c/src/spine/util.c b/spine-c/src/spine/extension.c similarity index 90% rename from spine-c/src/spine/util.c rename to spine-c/src/spine/extension.c index d24890a8b..d9283ba8f 100644 --- a/spine-c/src/spine/util.c +++ b/spine-c/src/spine/extension.c @@ -23,21 +23,20 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -#include +#include #include -const char* readFile (const char* path) { +char* _readFile (const char* path, int* length) { FILE *file = fopen(path, "rb"); if (!file) return 0; fseek(file, 0, SEEK_END); - long length = ftell(file); + *length = ftell(file); fseek(file, 0, SEEK_SET); - char* data = MALLOC(char, length + 1); - fread(data, 1, length, file); + char* data = MALLOC(char, *length); + fread(data, 1, *length, file); fclose(file); - data[length] = '\0'; return data; } diff --git a/spine-c/src/spine/util.h b/spine-c/src/spine/util.h deleted file mode 100644 index 8c606bf7e..000000000 --- a/spine-c/src/spine/util.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013, Esoteric Software - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ******************************************************************************/ - -#ifndef SPINE_UTIL_H_ -#define SPINE_UTIL_H_ - -#include -#include - -#ifdef __cplusplus -namespace spine { -extern "C" { -#endif - -/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const. */ -#define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)malloc(strlen(FROM)), FROM) - -/* Read file at specific path to a new char[]. Return value must be freed. */ -const char* readFile (const char* path); - -#ifdef __cplusplus -} -} -#endif - -#endif /* SPINE_UTIL_H_ */