Example #1
0
/**
 * Parse a comment in with "slash splat" or double slash notation,
 * leave the reader on the first character after the last end of comment mark.
 */
static inline int parseComment(struct Reader* reader)
{
    char chars[2];
    int ret = Reader_read(reader, &chars, 2);
    if (ret) {
        printf("Warning: expected comment\n");
        return OUT_OF_CONTENT_TO_READ;
    }
    if (chars[0] != '/') {
        printf("Warning: expected a comment starting with '/', instead found '%c'\n",chars[0]);
        return UNPARSABLE;
    }
    switch (chars[1]) {
        case '*':;
            do {
                readUntil('*', reader);
            } while (!(ret = Reader_read(reader, &chars, 1)) && chars[0] != '/');
            if (ret) {
                printf("Unterminated multiline comment\n");
                return OUT_OF_CONTENT_TO_READ;
            }
            return 0;
        case '/':;
            return readUntil('\n', reader);
        default:
            printf("Warning: expected a comment starting with \"//\" or \"/*\", "
                   "instead found \"/%c\"\n",chars[1]);
            return UNPARSABLE;
    }
}
Example #2
0
static inline int parseString(struct Reader* reader,
                              struct Allocator* allocator,
                              String** output)
{
    #define BUFF_SZ (1<<8)
    #define BUFF_MAX (1<<20)

    int curSize = BUFF_SZ;
    struct Allocator* localAllocator = Allocator_child(allocator);
    uint8_t* buffer = Allocator_malloc(localAllocator, curSize);
    if (readUntil('"', reader) || Reader_read(reader, buffer, 1)) {
        printf("Unterminated string\n");
        Allocator_free(localAllocator);
        return OUT_OF_CONTENT_TO_READ;
    }
    for (int i = 0; i < BUFF_MAX - 1; i++) {
        if (buffer[i] == '\\') {
            // \x01 (skip the x)
            Reader_skip(reader, 1);
            uint8_t hex[2];
            if (Reader_read(reader, (char*)hex, 2)) {
                printf("Unexpected end of input parsing escape sequence\n");
                Allocator_free(localAllocator);
                return OUT_OF_CONTENT_TO_READ;
            }
            int byte = Hex_decodeByte(hex[0], hex[1]);
            if (byte == -1) {
                printf("Invalid escape \"%c%c\" after \"%.*s\"\n",hex[0],hex[1],i+1,buffer);
                Allocator_free(localAllocator);
                return UNPARSABLE;
            }
            buffer[i] = (uint8_t) byte;
        } else if (buffer[i] == '"') {
            *output = String_newBinary((char*)buffer, i, allocator);
            Allocator_free(localAllocator);
            return 0;
        }
        if (i == curSize - 1) {
            curSize <<= 1;
            buffer = Allocator_realloc(localAllocator, buffer, curSize);
        }
        if (Reader_read(reader, buffer + i + 1, 1)) {
            if (i+1 <= 20) {
                printf("Unterminated string \"%.*s\"\n", i+1, buffer);
            } else {
                printf("Unterminated string starting with \"%.*s...\"\n", 20, buffer);
            }
            Allocator_free(localAllocator);
            return OUT_OF_CONTENT_TO_READ;
        }
    }

    printf("Maximum string length of %d bytes exceeded.\n",BUFF_SZ);
    Allocator_free(localAllocator);
    return UNPARSABLE;

    #undef BUFF_SZ
    #undef BUFF_MAX
}
/** @see BencSerializer.h */
static int32_t parseString(struct Reader* reader,
                           struct Allocator* allocator,
                           String** output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3

    /* Strings longer than 1*10^21-1 represent numbers definitly larger than uint64. */
    #define NUMBER_MAXLENGTH 21
    char number[32];
    char nextChar;
    int ret;

    /* Parse the size of the string. */
    size_t i = 0;
    for (i = 0; ; i++) {
        ret = Reader_read(reader, &nextChar, 1);
        if (ret != 0) {
            return OUT_OF_CONTENT_TO_READ;
        }
        if (nextChar == ':') {
            /* Found the separator. */
            break;
        }
        if (nextChar < '0' || nextChar > '9') {
            /* Invalid character. */
            return UNPARSABLE;
        }
        if (i >= NUMBER_MAXLENGTH) {
            /* Massive huge number. */
            return UNPARSABLE;
        }
        number[i] = nextChar;
    }
    number[i] = '\0';
    size_t length = strtoul(number, NULL, 10);

    char* bytes = Allocator_malloc(allocator, length + 1);
    String* string = Allocator_malloc(allocator, sizeof(String));

    /* Put a null terminator after the end so it can be treated as a normal string. */
    bytes[length] = '\0';

    if (Reader_read(reader, bytes, length) != 0) {
        return OUT_OF_CONTENT_TO_READ;
    }
    string->bytes = bytes;
    string->len = length;

    *output = string;

    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
    #undef NUMBER_MAXLENGTH
}
/** @see BencSerializer.h */
static int32_t parseList(struct Reader* reader,
                         struct Allocator* allocator,
                         List* output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3

    char nextChar;
    if (Reader_read(reader, &nextChar, 1) != 0) {
        return OUT_OF_CONTENT_TO_READ;
    }
    if (nextChar != 'l') {
        return UNPARSABLE;
    }

    Object* element;
    struct List_Item* thisEntry = NULL;
    struct List_Item** lastEntryPointer = output;
    int ret;

    if (Reader_read(reader, &nextChar, 0) != 0) {
        return OUT_OF_CONTENT_TO_READ;
    }
    *lastEntryPointer = NULL;

    while (nextChar != 'e') {
        ret = parseGeneric(reader, allocator, &element);
        if (ret != 0) {
            return ret;
        }
        thisEntry = Allocator_malloc(allocator, sizeof(struct List_Item));
        thisEntry->elem = element;

        /* Read backwards so that the list reads out forward. */
        *lastEntryPointer = thisEntry;
        lastEntryPointer = &(thisEntry->next);

        if (Reader_read(reader, &nextChar, 0) != 0) {
            return OUT_OF_CONTENT_TO_READ;
        }
    }

    if (thisEntry) {
        thisEntry->next = NULL;
    }

    /* move the pointer to after the 'e' at the end of the list. */
    Reader_skip(reader, 1);

    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
}
Example #5
0
static ALuint read_le32(Reader *stream)
{
    ALubyte buf[4];
    if(Reader_read(stream, buf, 4) != 4)
        return 0;
    return (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
}
Example #6
0
static ALushort read_le16(Reader *stream)
{
    ALubyte buf[2];
    if(Reader_read(stream, buf, 2) != 2)
        return 0;
    return (buf[1]<<8) | buf[0];
}
Example #7
0
static ALubyte read_8(Reader *stream)
{
    ALubyte buf[1];
    if(Reader_read(stream, buf, 1) != 1)
        return 0;
    return buf[0];
}
Example #8
0
/** @see BencSerializer.h */
static int32_t parseDictionary(struct Reader* reader,
                               struct Allocator* allocator,
                               Dict* output)
{
    uint8_t nextChar;
    readUntil('{', reader);

    String* key;
    Object* value;
    struct Dict_Entry* entryPointer;
    struct Dict_Entry* lastEntryPointer = NULL;
    int ret = 0;

    for (;;) {
        while (!ret) {
            ret = Reader_read(reader, &nextChar, 0);
            switch (nextChar) {
                case '"':
                    break;

                case '}':
                    Reader_skip(reader, 1);
                    *output = lastEntryPointer;
                    return 0;

                case '/':
                    parseComment(reader);
                    continue;

                default:
                    Reader_skip(reader, 1);
                    continue;
            }
            break;
        }
        if (ret) {
            printf("Unterminated dictionary\n");
            return OUT_OF_CONTENT_TO_READ;
        }

        // Get key and value.
        if ((ret = parseString(reader, allocator, &key)) != 0) {
            return ret;
        }

        readUntil(':', reader);

        if ((ret = parseGeneric(reader, allocator, &value)) != 0) {
            return ret;
        }

        /* Allocate the entry. */
        entryPointer = Allocator_malloc(allocator, sizeof(struct Dict_Entry));

        entryPointer->next = lastEntryPointer;
        entryPointer->key = key;
        entryPointer->val = value;
        lastEntryPointer = entryPointer;
    }
}
Example #9
0
/** @see BencSerializer.h */
static int32_t parseint64_t(struct Reader* reader,
                            int64_t* output)
{
    uint8_t buffer[32];

    for (int i = 0; i < 21; i++) {
        int32_t status = Reader_read(reader, buffer + i, 0);
        if (i == 0 && buffer[i] == '-' && status == 0) {
            // It's just a negative number, no need to fail it.
            continue;
        }
        if (buffer[i] < '0' || buffer[i] > '9' || status != 0 /* end of input */) {
            buffer[i] = '\0';
            int64_t out = strtol((char*)buffer, NULL, 10);
            // Failed parse causes 0 to be set.
            if (out == 0 && buffer[0] != '0' && (buffer[0] != '-' || buffer[1] != '0')) {
                printf("Failed to parse \"%s\": not a number\n",buffer);
                return UNPARSABLE;
            }
            if ((out == INT64_MAX || out == INT64_MIN) && errno == ERANGE) {
                printf("Failed to parse \"%s\": number too large/small\n",buffer);
                return UNPARSABLE;
            }
            *output = out;
            return 0;
        }
        Reader_skip(reader, 1);
    }

    // Larger than the max possible int64.
    buffer[22] = '\0';
    printf("Failed to parse \"%s\": number too large\n",buffer);
    return UNPARSABLE;
}
Example #10
0
int main()
{
    struct Allocator* alloc = MallocAllocator_new(1024);
    struct Random* rand = Random_new(alloc, NULL, NULL);

    FILE* tmp = tmpfile();
    uint8_t buffer1[2048];
    size_t checkSize;
    Random_bytes(rand, buffer1, 2048);
    checkSize = fwrite(buffer1, 1, 2048, tmp);
    if (checkSize != 2048)
    {
        return 1;
    }

    uint8_t buffer2[1024];
    rewind(tmp);
    struct Reader* r = FileReader_new(tmp, alloc);

    Reader_read(r, buffer2, 128);
    Reader_skip(r, 128);
    Reader_read(r, buffer2+128, 128);
    Reader_skip(r, 512);
    Reader_read(r, buffer2+128+128, 256);
    Reader_skip(r, 300);
    Reader_read(r, buffer2+128+128+256, 128);

    Assert_true(r->bytesRead == 128+128+128+512+256+300+128);

    uint8_t* ptr1 = buffer1;
    uint8_t* ptr2 = buffer2;

    #define SKIP(x) ptr1 += x
    #define CMP(x) Assert_true(!Bits_memcmp(ptr1, ptr2, x)); ptr1 += x; ptr2 += x

    CMP(128);
    SKIP(128);
    CMP(128);
    SKIP(512);
    CMP(256);
    SKIP(300);
    CMP(128);

    Allocator_free(alloc);
    return 0;
}
Example #11
0
static void skip(Reader *stream, ALuint amt)
{
    while(amt > 0 && !READERR(stream))
    {
        char buf[4096];
        amt -= Reader_read(stream, buf, minu(sizeof(buf), amt));
    }
}
Example #12
0
static void PresetHeader_read(PresetHeader *self, Reader *stream)
{
    Reader_read(stream, self->mName, sizeof(self->mName));
    self->mPreset = read_le16(stream);
    self->mBank = read_le16(stream);
    self->mZoneIdx = read_le16(stream);
    self->mLibrary = read_le32(stream);
    self->mGenre = read_le32(stream);
    self->mMorphology = read_le32(stream);
}
Example #13
0
/**
 * Read until 1 char after the target character.
 */
static inline int readUntil(uint8_t target, struct Reader* reader)
{
    uint8_t nextChar;
    do {
        if (Reader_read(reader, (char*)&nextChar, 1)) {
            printf("Unexpected end of input while looking for '%c'\n",target);
            return OUT_OF_CONTENT_TO_READ;
        }
    } while (nextChar != target);
    return 0;
}
/** @see BencSerializer.h */
static int32_t parseint64_t(struct Reader* reader,
                            int64_t* output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3
    char buffer[32];
    int i;
    for (i = 0; ; i++) {
        if (Reader_read(reader, buffer + i, 1) != 0) {
            return OUT_OF_CONTENT_TO_READ;
        }
        if (i == 0) {
            if (buffer[i] != 'i') {
                /* Not an int. */
                return UNPARSABLE;
            } else {
                continue;
            }
        }
        if (buffer[i] == 'e') {
            break;
        }
        if (i == 1 && buffer[i] == '-') {
            /* It's just a negative number, no need to fail it. */
            continue;
        }
        if (buffer[i] < '0' || buffer[i] > '9') {
            return UNPARSABLE;
        }
        if (i > 21) {
            /* Larger than the max possible int64. */
            return UNPARSABLE;
        }
    }

    /* buffer + 1, skip the 'i' */
    int64_t out = strtol(buffer + 1, NULL, 10);

    /* Failed parse causes 0 to be set. */
    if (out == 0 && buffer[1] != '0' && (buffer[1] != '-' || buffer[2] != '0')) {
        return UNPARSABLE;
    }
    if ((out == LONG_MAX || out == LONG_MIN) && errno == ERANGE) {
        /* errno (holds nose) */
        return UNPARSABLE;
    }

    *output = out;
    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
}
Example #15
0
static void SampleHeader_read(SampleHeader *self, Reader *stream)
{
    Reader_read(stream, self->mName, sizeof(self->mName));
    self->mStart = read_le32(stream);
    self->mEnd = read_le32(stream);
    self->mStartloop = read_le32(stream);
    self->mEndloop = read_le32(stream);
    self->mSampleRate = read_le32(stream);
    self->mOriginalKey = read_8(stream);
    self->mCorrection = read_8(stream);
    self->mSampleLink = read_le16(stream);
    self->mSampleType = read_le16(stream);
}
Example #16
0
struct VersionList* VersionList_parse(String* str, struct Allocator* alloc)
{
    const uint8_t numberSize = str->bytes[0];
    if (str->len < 1 || numberSize == 0 || numberSize > 4) {
        return NULL;
    }

    uint32_t length = (str->len - 1) / numberSize;

    if ((length * numberSize) != (str->len - 1)) {
        return NULL;
    }

    struct VersionList* list = VersionList_new(length, alloc);
    struct Reader* r = ArrayReader_new(str->bytes + 1, str->len - 1, alloc);
    for (int i = 0; i < (int)list->length; i++) {
        uint32_t ver = 0;
        Reader_read(r, (uint8_t*) &ver, numberSize);
        ver = Endian_bigEndianToHost32(ver);
        list->versions[i] = ver >> ((4-numberSize) * 8);
    }
    return list;
}
Example #17
0
static void InstrumentHeader_read(InstrumentHeader *self, Reader *stream)
{
    Reader_read(stream, self->mName, sizeof(self->mName));
    self->mZoneIdx = read_le16(stream);
}
Example #18
0
/** @see BencSerializer.h */
static int32_t parseList(struct Reader* reader,
                         struct Allocator* allocator,
                         List* output)
{
    char nextChar;
    readUntil('[', reader);

    Object* element;
    struct List_Item* thisEntry = NULL;
    struct List_Item** lastEntryPointer = output;
    int ret;

    for (;;) {
        for (;;) {
            if (Reader_read(reader, &nextChar, 0) != 0) {
                printf("Unterminated list\n");
                return OUT_OF_CONTENT_TO_READ;
            }
            if (nextChar == '/') {
                if ((ret = parseComment(reader)) != 0) {
                    return ret;
                }
                continue;
            }
            switch (nextChar) {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                case '[':
                case '{':
                case '"':
                    break;

                case ']':
                    Reader_skip(reader, 1);
                    return 0;

                default:
                    // FIXME: silently skipping anything we don't understand
                    // might not be the best idea
                    Reader_skip(reader, 1);
                    continue;
            }
            break;
        }

        if ((ret = parseGeneric(reader, allocator, &element)) != 0) {
            return ret;
        }
        thisEntry = Allocator_malloc(allocator, sizeof(struct List_Item));
        thisEntry->elem = element;
        thisEntry->next = NULL;

        // Read backwards so that the list reads out forward.
        *lastEntryPointer = thisEntry;
        lastEntryPointer = &(thisEntry->next);
    }
}
/**
 * Parse an unknown data type.
 * This is not exposed to the world because it is expected that one would
 * know what type they are parsing to begin with. This is used by parseDictionary
 * and parseList to grab pieces of data which are of unknown type and parse them.
 *
 * @param reader the reader to get the stream of data from.
 * @param allocator the means of storing the parsed data.
 * @param output a pointer which will be pointed to the output.
 */
static int32_t parseGeneric(struct Reader* reader,
                            struct Allocator* allocator,
                            Object** output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3

    int ret;
    char firstChar;
    ret = Reader_read(reader, &firstChar, 0);
    if (ret != 0) {
        return OUT_OF_CONTENT_TO_READ;
    }

    Object* out = Allocator_malloc(allocator, sizeof(Object));

    if (firstChar <= '9' && firstChar >= '0') {
        /* It's a string! */
        String* string = NULL;
        ret = parseString(reader, allocator, &string);
        out->type = Object_STRING;
        out->as.string = string;
    } else {
        switch (firstChar) {
            case 'i':;
                /* int64_t. Int is special because it is not a pointer but a int64_t. */
                int64_t bint = 0;
                ret = parseint64_t(reader, &bint);
                out->type = Object_INTEGER;
                out->as.number = bint;
                break;
            case 'l':;
                /* List. */
                List* list = Allocator_calloc(allocator, sizeof(List), 1);
                ret = parseList(reader, allocator, list);
                out->type = Object_LIST;
                out->as.list = list;
                break;
            case 'd':;
                /* Dictionary. */
                Dict* dict = Allocator_calloc(allocator, sizeof(Dict), 1);
                ret = parseDictionary(reader, allocator, dict);
                out->type = Object_DICT;
                out->as.dictionary = dict;
                break;
            default:
                return UNPARSABLE;
        }
    }

    if (ret != 0) {
        /* Something went wrong while parsing. */
        return ret;
    }

    *output = out;
    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
}
/** @see BencSerializer.h */
static int32_t parseDictionary(struct Reader* reader,
                               struct Allocator* allocator,
                               Dict* output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3

    char nextChar;
    if (Reader_read(reader, &nextChar, 1) < 0) {
        return OUT_OF_CONTENT_TO_READ;
    }
    if (nextChar != 'd') {
        /* Not a dictionary. */
        return UNPARSABLE;
    }

    String* key;
    Object* value;
    struct Dict_Entry* entryPointer;
    struct Dict_Entry* lastEntryPointer = NULL;
    int ret;

    for (;;) {
        /* Peek at the next char. */
        if (Reader_read(reader, &nextChar, 0) < 0) {
            /* Ran over read buffer. */
            return OUT_OF_CONTENT_TO_READ;
        }
        if (nextChar == 'e') {
            /* Got to the end. */
            break;
        }

        /* Get key and value. */
        ret = parseString(reader, allocator, &key);
        if (ret != 0) {
            return ret;
        }
        ret = parseGeneric(reader, allocator, &value);
        if (ret != 0) {
            return ret;
        }

        /* Allocate the entry. */
        entryPointer = Allocator_malloc(allocator, sizeof(struct Dict_Entry));

        entryPointer->next = lastEntryPointer;
        entryPointer->key = key;
        entryPointer->val = value;
        lastEntryPointer = entryPointer;
    }

    /* We got an 'e', leave the pointer on the next char after it. */
    Reader_skip(reader, 1);

    *output = lastEntryPointer;

    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
}
Example #21
0
static int32_t parseGeneric(struct Reader* reader,
                            struct Allocator* allocator,
                            Object** output)
{
    int ret = 0;
    char firstChar;

    for (;;) {
        ret = Reader_read(reader, &firstChar, 0);
        switch (firstChar) {
            case ' ':
            case '\r':
            case '\n':
            case '\t':
                Reader_skip(reader, 1);
                continue;

            case '/':;
                if ((ret = parseComment(reader)) != 0) {
                    return ret;
                }
                continue;

            default:
                break;
        }
        if (ret) {
            printf("Unexpected end of input\n");
            return OUT_OF_CONTENT_TO_READ;
        }
        break;
    }

    Object* out = Allocator_malloc(allocator, sizeof(Object));

    switch (firstChar) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':;
            // int64_t. Int is special because it is not a pointer but a int64_t.
            int64_t bint;
            if ((ret = parseint64_t(reader, &bint)) == UNPARSABLE) {
                break;
            }
            out->type = Object_INTEGER;
            out->as.number = bint;
            break;

        case '[':;
            // List.
            List* list = Allocator_calloc(allocator, sizeof(List), 1);
            ret = parseList(reader, allocator, list);
            out->type = Object_LIST;
            out->as.list = list;
            break;

        case '{':;
            // Dictionary
            Dict* dict = Allocator_calloc(allocator, sizeof(Dict), 1);
            ret = parseDictionary(reader, allocator, dict);
            out->type = Object_DICT;
            out->as.dictionary = dict;
            break;

        case '"':;
            // String
            String* string = NULL;
            ret = parseString(reader, allocator, &string);
            out->type = Object_STRING;
            out->as.string = string;
            break;

        default:
            printf("While looking for something to parse: "
                   "expected one of 0 1 2 3 4 5 6 7 8 9 [ { \", found '%c'\n", firstChar);
            return UNPARSABLE;
    }

    if (ret != 0) {
        // Something went wrong while parsing.
        return ret;
    }

    *output = out;
    return 0;
}