#include "assert.h" #include "characters.h" #include "errors/errors.h" #include "errors/exceptions.h" #include "files/fastreadbyte.h" #include "files/files.h" #include "files/filters/filters.h" #include "files/filters/methods.h" #include "object.h" #include "types/boolean.h" #include "types/composites/composites.h" #include "types/numbers/numbers.h" #define error goto finally object ASCII85Decoder(const object instance, object string) { assert(instance.type == arraytype); assert(instance.length == filterarray); assert(instance.array); assert(string.type == stringtype); if (string.length) assert(string.string); const natural remaining = string.length; string.length = 0; const object source = instance.array[stream]; for ( object eod = null; instance.array[EOD].type != booleantype; instance.array[EOD] = eod ) { const object digit = memory(5); natural padding = 0; natural bytes = 0; while (bytes < digit.length) { byte character = 0; if (readbyte(&character, source) == false) { instance.array[EOD] = boolean(false); error; } if (ascii85[character]) { digit.string[bytes++] = (byte)ascii85[character]; } else if (character == 'z') { if (bytes == 0) { while (bytes < digit.length) digit.string[bytes++] = 0; } else { error; } } else if (character == '~') { if (readbyte(&character, source) && character == '>') { if (bytes != 1) { while (bytes < digit.length) { digit.string[bytes++] = (byte)ascii85['u']; ++padding; } eod = boolean(true); } else { error; } } else { error; } } else if (whitespace[character] == false) { error; } } bytes = 0; natural number = 0; switch (digit.length) { case 5: { number += digit.string[bytes++]; } case 4: { number *= 85; number += digit.string[bytes++]; } case 3: { number *= 85; number += digit.string[bytes++]; } case 2: { number *= 85; number += digit.string[bytes++]; } case 1: { static const natural limit = (1lu << 31) | ((1lu << 31) - 1); if (number > limit / 85) error; number *= 85; if (number > limit - digit.string[bytes]) error; number += digit.string[bytes++]; } } object binary = memory(4); binary.string[3] = (byte)(number); number >>= 8; binary.string[2] = (byte)(number); number >>= 8; binary.string[1] = (byte)(number); number >>= 8; binary.string[0] = (byte)(number); assert(padding < binary.length); binary.length -= padding; for (natural data = 0; data < binary.length; ++data) { if (string.length < remaining) string.string[string.length++] = binary.string[data]; else error; } } finally: return string; } #undef error