void ChanneledJsonDecompressor::readMap(int64_t length, dynamic* outMapObj) { *outMapObj = dynamic::object(); int64_t keyType; for (int64_t i = 0; i < length; ++i) { dynamic curKey(nullptr); keyType = readVarInt(CHANNEL_KEYS); if (keyType == KEY_TYPE_STRING) { uint64_t keyLength = readVarInt(CHANNEL_KEYS); readString(keyLength, CHANNEL_KEYS, &curKey); // saving for memoised keys memoKeys_[memoKeysNext_] = curKey.asString(); ++memoKeysNext_; } else { // key type memoised (KEY_TYPE_STATIC is not used yet) curKey = memoKeys_[keyType - KEY_TYPE_MEMOISED_BASE]; } // reading value dynamic value(nullptr); // dummy initialization read(&value); //appending result outMapObj->operator[](curKey) = value; } }
/** Check if id is a result and move to next id * Set ppExpr = NULL, if at end */ static bool exprCheckAndMove(expr **ppExpr, sqlite3_int64 id){ assert(ppExpr && *ppExpr); if((*ppExpr)->eType & EXPR_OP){ bool r1 = exprCheckAndMove(&(*ppExpr)->expr.op.expr1, id); bool r2 = exprCheckAndMove(&(*ppExpr)->expr.op.expr2, id); if((*ppExpr)->eType == EXPR_AND){ /* If one of them is at end, we're done */ if(!(*ppExpr)->expr.op.expr1 || !(*ppExpr)->expr.op.expr2){ exprRelease((*ppExpr)->expr.op.expr1); exprRelease((*ppExpr)->expr.op.expr2); sqlite3_free(*ppExpr); *ppExpr = NULL; } return r1 && r2; } assert((*ppExpr)->eType == EXPR_OR); if(!(*ppExpr)->expr.op.expr1 && !(*ppExpr)->expr.op.expr2){ sqlite3_free(*ppExpr); *ppExpr = NULL; }else if(!(*ppExpr)->expr.op.expr1){ expr* expr2 = (*ppExpr)->expr.op.expr2; sqlite3_free(*ppExpr); *ppExpr = expr2; }else if(!(*ppExpr)->expr.op.expr2){ expr* expr1 = (*ppExpr)->expr.op.expr1; sqlite3_free(*ppExpr); *ppExpr = expr1; } return r1 || r2; }else{ assert((*ppExpr)->eType == EXPR_TRIGRAM); while((*ppExpr)->expr.trigram.nSize > 0 && (*ppExpr)->expr.trigram.curId < id){ sqlite3_int64 prev = (*ppExpr)->expr.trigram.curId; int read = readVarInt((*ppExpr)->expr.trigram.docList, &(*ppExpr)->expr.trigram.curId); (*ppExpr)->expr.trigram.curId += prev; (*ppExpr)->expr.trigram.nSize -= read; (*ppExpr)->expr.trigram.docList += read; } bool retval = (*ppExpr)->expr.trigram.curId == id; /* Check if we have to move forward */ if((*ppExpr)->expr.trigram.curId <= id){ /* If we can't we're at the end and done */ if((*ppExpr)->expr.trigram.nSize == 0){ sqlite3_free(*ppExpr); *ppExpr = NULL; }else{ sqlite3_int64 prev = (*ppExpr)->expr.trigram.curId; int read = readVarInt((*ppExpr)->expr.trigram.docList, &(*ppExpr)->expr.trigram.curId); (*ppExpr)->expr.trigram.curId += prev; (*ppExpr)->expr.trigram.nSize -= read; (*ppExpr)->expr.trigram.docList += read; } } return retval; } }
/** Create a trigram expression for matching against a single trigram */ int exprTrigram(expr **ppExpr, trilite_vtab *pTrgVtab, trilite_trigram trigram){ int rc = SQLITE_OK; sqlite3_blob *pBlob; char *zTable = sqlite3_mprintf("%s_index", pTrgVtab->zName); /* Open the blob */ rc = sqlite3_blob_open(pTrgVtab->db, pTrgVtab->zDb, zTable, "doclist", trigram, 0, &pBlob); sqlite3_free(zTable); /* If we didn't get a blob */ if(rc != SQLITE_OK){ *ppExpr = NULL; return SQLITE_OK; } /* Get size of blob */ int nSize = sqlite3_blob_bytes(pBlob); /* Allocate space for expr and doclist at the same time */ *ppExpr = (expr*)sqlite3_malloc(sizeof(expr) + nSize); /* Set the expr */ (*ppExpr)->eType = EXPR_TRIGRAM; (*ppExpr)->expr.trigram.docList = ((unsigned char*)(*ppExpr)) + sizeof(expr); (*ppExpr)->expr.trigram.nSize = nSize; /* Read doclist into memory */ sqlite3_blob_read(pBlob, (*ppExpr)->expr.trigram.docList, nSize, 0); /* Release blob */ sqlite3_blob_close(pBlob); /* Read first id */ int read = readVarInt((*ppExpr)->expr.trigram.docList, &(*ppExpr)->expr.trigram.curId); (*ppExpr)->expr.trigram.curId += DELTA_LIST_OFFSET; (*ppExpr)->expr.trigram.nSize -= read; (*ppExpr)->expr.trigram.docList += read; return rc; }
MidiEvent* parseEvent(uint8_t const*& dataStart, uint8_t lastEventTypeByte) { uint8_t eventTypeByte = *dataStart++; if ((eventTypeByte & 0xf0) == 0xf0) { /* system / meta event */ if (eventTypeByte == 0xff) { /* meta event */ uint8_t subtypeByte = *dataStart++; int length = readVarInt(dataStart); switch(subtypeByte) { case 0x00: { if (length != 2) throw "Expected length for sequenceNumber event is 2"; SequenceNumberEvent* event = new SequenceNumberEvent(); event->number = * (uint16_t*) dataStart; dataStart += 2; return event; } case 0x01: { TextEvent* event = new TextEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x02: { CopyrightNoticeEvent* event = new CopyrightNoticeEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x03: { TrackNameEvent* event = new TrackNameEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x04: { InstrumentNameEvent* event = new InstrumentNameEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x05: { LyricsEvent* event = new LyricsEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x06: { MarkerEvent* event = new MarkerEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x07: { CuePointEvent* event = new CuePointEvent(); event->text.assign((char*) dataStart, length); dataStart += length; return event; } case 0x20: { if (length != 1) throw "Expected length for midiChannelPrefix event is 1"; MidiChannelPrefixEvent* event = new MidiChannelPrefixEvent(); event->channel = *(uint8_t*) dataStart; ++dataStart; return event; } case 0x2f: { if (length != 0) throw "Expected length for endOfTrack event is 0"; EndOfTrackEvent* event = new EndOfTrackEvent(); return event; } case 0x51: { if (length != 3) throw "Expected length for setTempo event is 3"; SetTempoEvent* event = new SetTempoEvent(); event->microsecondsPerBeat = readInt24(dataStart); return event; } case 0x54: { if (length != 5) throw "Expected length for smpteOffset event is 5"; SmpteOffsetEvent* event = new SmpteOffsetEvent(); uint8_t hourByte = *dataStart++; switch (hourByte & 0x60) { case 0x00: event->framerate = 24; break; case 0x20: event->framerate = 25; break; case 0x40: event->framerate = 29; break; case 0x60: event->framerate = 30; break; } event->hour = hourByte & 0x1f; event->min = int(*dataStart++); event->sec = int(*dataStart++); event->frame = int(*dataStart++); event->subframe = int(*dataStart++); return event; } case 0x58: { if (length != 4) throw "Expected length for timeSignature event is 4"; TimeSignatureEvent* event = new TimeSignatureEvent(); event->numerator = int(*dataStart++); event->denominator = int(powf(2.0f, float(*dataStart++))); event->metronome = int(*dataStart++); event->thirtyseconds = int(*dataStart++); return event; } case 0x59: { if (length != 2) throw "Expected length for keySignature event is 2"; KeySignatureEvent* event = new KeySignatureEvent(); event->key = int(*dataStart++); event->scale = int(*dataStart++); return event; } case 0x7f: { SequencerSpecificEvent* event = new SequencerSpecificEvent(); event->data = new uint8_t[length]; memcpy(event->data, dataStart, length); dataStart += length; return event; } } // console.log("Unrecognised meta event subtype: " + subtypeByte); UnknownEvent* event = new UnknownEvent(); event->data = new uint8_t[length]; memcpy(event->data, dataStart, length); dataStart += length; return event; } else if (eventTypeByte == 0xf0) { int length = readVarInt(dataStart); SysExEvent* event = new SysExEvent(); event->data = new uint8_t[length]; memcpy(event->data, dataStart, length); dataStart += length; return event; } else if (eventTypeByte == 0xf7) { int length = readVarInt(dataStart); DividedSysExEvent* event = new DividedSysExEvent(); event->data = new uint8_t[length]; memcpy(event->data, dataStart, length); dataStart += length; return event; } else { throw "Unrecognised MIDI event type byte"; // eventTypeByte; } } else { /* channel event */ ChannelEvent* event = new ChannelEvent(); int param1; if ((eventTypeByte & 0x80) == 0) { // Running status is described here: // http://home.roadrunner.com/~jgglatt/tech/midispec/run.htm // running status - reuse lastEventTypeByte as the event type. // eventTypeByte is actually the first parameter // param1 = eventTypeByte; eventTypeByte = lastEventTypeByte; } else { param1 = int(*dataStart++); lastEventTypeByte = eventTypeByte; } event->midiCommand = eventTypeByte; event->param1 = param1; event->param2 = 0xff; // don't transmit this value switch (eventTypeByte & 0xf0) { case 0x80: // note off event->param2 = int(*dataStart++); return event; case 0x90: // note on event->param2 = int(*dataStart++); // velocity return event; case 0xa0: // after touch event->param2 = int(*dataStart++); // amount return event; case 0xb0: // controller event->param2 = int(*dataStart++); // amount return event; case 0xc0: // program change return event; case 0xd0: // channel after touch return event; case 0xe0: // pitch bend event->param2 = int(*dataStart++); return event; default: throw "Unrecognised MIDI event type"; } } throw "Unparsed event"; }
void ChanneledJsonDecompressor::read(dynamic* outObj) { uint8_t curType = readType(); // Map if (inRange(curType, TYPE_SHORT_MAP_BASE, SHORT_TYPE_LENGTH)) { readMap(curType - TYPE_SHORT_MAP_BASE, outObj); return; } if (curType == TYPE_LONG_MAP) { int64_t mapLength = readVarInt(CHANNEL_MAPLEN); readMap(mapLength, outObj); return; } // Array if (inRange(curType, TYPE_SHORT_ARRAY_BASE, SHORT_TYPE_LENGTH)) { readArray(curType - TYPE_SHORT_ARRAY_BASE, outObj); return; } if (curType == TYPE_LONG_ARRAY) { int64_t arrayLength = readVarInt(CHANNEL_ARRAYLEN); readArray(arrayLength, outObj); return; } // String - different types if (curType == TYPE_MEMOISED_STRING) { int memoisedIdx = readVarInt(CHANNEL_MEMOSTRS); *outObj = memoStrings_[memoisedIdx]; return; } if (inRange(curType, TYPE_SHORT_STRING_BASE, SHORT_TYPE_LENGTH)) { uint32_t stringLength = curType - TYPE_SHORT_STRING_BASE; readString(stringLength, CHANNEL_STRS, outObj); memoStrings_[memoStringsNext_] = outObj->asString(); ++memoStringsNext_; return; } if (curType == TYPE_STRING_SIZE) { uint32_t stringLength = readVarInt(CHANNEL_STRLEN); readString(stringLength, CHANNEL_STRS, outObj); memoStrings_[memoStringsNext_] = outObj->asString(); ++memoStringsNext_; return; } // Boolean if (curType == TYPE_BOOL_TRUE) { *outObj = true; return; } if (curType == TYPE_BOOL_FALSE) { *outObj = false; return; } // Integer if (inRange(curType, TYPE_SMALL_INT_BASE, SHORT_TYPE_LENGTH)) { *outObj = curType - TYPE_SMALL_INT_BASE; return; } if (curType == TYPE_LONG_INT) { *outObj = readVarInt(CHANNEL_INTS); return; } // None if (curType == TYPE_NONE) { *outObj = nullptr; return; } // Double if (curType == TYPE_DOUBLE) { readDouble(outObj); return; } //TODO(noamler) - unknown type error handling. Log? *outObj = nullptr; }