Index: src/OFExceptions.h ================================================================== --- src/OFExceptions.h +++ src/OFExceptions.h @@ -41,13 +41,31 @@ @interface OFOverflowException: OFException + newWithObject: (id)obj; - initWithObject: (id)obj; @end -@interface OFReadFailedException: OFException +@interface OFOpenFileFailedException: OFException ++ newWithObject: (id)obj + andPath: (const char*)path + andMode: (const char*)mode; +- initWithObject: (id)obj + andPath: (const char*)path + andMode: (const char*)mode; +@end + +@interface OFReadOrWriteFailedException: OFException + newWithObject: (id)obj andSize: (size_t)size andNItems: (size_t)nitems; +@end + +@interface OFReadFailedException: OFReadOrWriteFailedException +- initWithObject: (id)obj + andSize: (size_t)size + andNItems: (size_t)nitems; +@end + +@interface OFWriteFailedException: OFReadOrWriteFailedException - initWithObject: (id)obj andSize: (size_t)size andNItems: (size_t)nitems; @end Index: src/OFExceptions.m ================================================================== --- src/OFExceptions.m +++ src/OFExceptions.m @@ -18,12 +18,13 @@ return [[OFException alloc] initWithObject: obj]; } - initWithObject: (id)obj { + self = [super init]; @throw self; - return [super init]; + return self; } @end @implementation OFNoMemException + newWithObject: (id)obj @@ -37,12 +38,13 @@ andSize: (size_t)size { fprintf(stderr, "ERROR: Could not allocate %zu bytes for object %s!\n", size, [obj name]); + self = [super init]; @throw self; - return [super init]; + return self; } @end @implementation OFNotImplementedException + newWithObject: (id)obj @@ -56,12 +58,13 @@ andMethod: (const char*)method { fprintf(stderr, "ERROR: Requested method %s not implemented in %s!\n", method, [obj name]); + self = [super init]; @throw self; - return [super init]; + return self; } @end @implementation OFMemNotPartOfObjException + newWithObject: (id)obj @@ -78,12 +81,13 @@ "object %s!\n" "ERROR: -> Not changing memory allocation!\n" "ERROR: (Hint: It is possible that you tried to free the same " "memory twice!)\n", ptr, [obj name]); + self = [super init]; @throw self; - return [super init]; + return self; } @end @implementation OFOverflowException + newWithObject: (id)obj @@ -93,31 +97,72 @@ - initWithObject: (id)obj { fprintf(stderr, "ERROR: Overflow in object %s!\n", [obj name]); + self = [super init]; + @throw self; + return self; +} +@end + +@implementation OFOpenFileFailedException ++ newWithObject: (id)obj + andPath: (const char*)path + andMode: (const char*)mode +{ + return [[OFOpenFileFailedException alloc] initWithObject: obj + andPath: path + andMode: mode]; +} + +- initWithObject: (id)obj + andPath: (const char*)path + andMode: (const char*)mode +{ + fprintf(stderr, "ERROR: Failed to open file %s with mode %s in " + "object %s!\n", path, mode, [self name]); + + self = [super init]; @throw self; - return [super init]; + return self; } @end -@implementation OFReadFailedException +@implementation OFReadOrWriteFailedException + newWithObject: (id)obj andSize: (size_t)size andNItems: (size_t)nitems { - return [[OFReadFailedException alloc] initWithObject: obj - andSize: size - andNItems: nitems]; + return [[OFReadOrWriteFailedException alloc] initWithObject: obj + andSize: size + andNItems: nitems]; } +@end +@implementation OFReadFailedException - initWithObject: (id)obj andSize: (size_t)size andNItems: (size_t)nitems { fprintf(stderr, "ERROR: Failed to read %zu items of size %zu in " "object %s!\n", nitems, size, [obj name]); + self = [super init]; + @throw self; + return self; +} +@end + +@implementation OFWriteFailedException +- initWithObject: (id)obj + andSize: (size_t)size + andNItems: (size_t)nitems +{ + fprintf(stderr, "ERROR: Failed to write %zu items of size %zu in " + "object %s!\n", nitems, size, [obj name]); + + self = [super init]; @throw self; - return [super init]; + return self; } @end Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -21,8 +21,15 @@ + newWithPath: (const char*)path andMode: (const char*)mode; - initWithPath: (const char*)path andMode: (const char*)mode; - free; +- (BOOL)isEndOfFile; +- (size_t)readIntoBuffer: (char*)buf + withSize: (size_t)size + andNItems: (size_t)nItems; - (char*)readWithSize: (size_t)size + andNItems: (size_t)nitems; +- (size_t)writeBuffer: (char*)buf + withSize: (size_t)size andNItems: (size_t)nitems; @end Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -37,30 +37,67 @@ - free { fclose(fp); return [super free]; } + +- (BOOL)isEndOfFile +{ + return feof(fp); +} + +- (size_t)readIntoBuffer: (char*)buf + withSize: (size_t)size + andNItems: (size_t)nitems +{ + size_t ret; + + if ((ret = fread(buf, size, nitems, fp)) == 0 && ![self isEndOfFile]) + [OFReadFailedException newWithObject: self + andSize: size + andNItems: nitems]; + + return ret; +} - (char*)readWithSize: (size_t)size andNItems: (size_t)nitems { uint64_t memsize; char *ret; - if ((memsize = (uint64_t)nitems * size) > 0xFFFFFFFF) { + if (size >= 0xFFFFFFFF || nitems >= 0xFFFFFFFF || + (memsize = (uint64_t)nitems * size) > 0xFFFFFFFF) { [OFOverflowException newWithObject: self]; return NULL; } ret = [self getMem: (size_t)memsize]; - if (fread(ret, size, nitems, fp) <= 0 && !feof(fp)) { + @try { + [self readIntoBuffer: ret + withSize: size + andNItems: nitems]; + } @catch (OFReadFailedException *e) { [self freeMem: ret]; - [OFReadFailedException newWithObject: self - andSize: size - andNItems: nitems]; + @throw e; return NULL; } + return ret; +} + +- (size_t)writeBuffer: (char*)buf + withSize: (size_t)size + andNItems: (size_t)nitems +{ + size_t ret; + + if ((ret = fwrite(buf, size, nitems, fp)) == 0 && + size != 0 && nitems != 0) + [OFWriteFailedException newWithObject: self + andSize: size + andNItems: nitems]; + return ret; } @end