/// <summary> /// Reads a record using the previous data available. /// TPS uses a stupid ( prossesing costly ) method to save space. It copies data from the last record if possible /// </summary> /// <param name="previous"></param> /// <param name="pageDataRandomAccess"></param> public TPSRecord(ref TPSRecord previous, ref RandomAccess pageDataRandomAccess) { //the flag tells us what data we should be copying _flags = pageDataRandomAccess.leByte(); if ((_flags & 0x80) != 0) { _recordLength = pageDataRandomAccess.leShort(); } else { _recordLength = previous.RecordLength; } if ((_flags & 0x40) != 0) { _headerLength = pageDataRandomAccess.leShort(); } else { _headerLength = previous.HeaderLength; } //The last part tells us how much actual record data we should copy int copy = _flags & 0x3F; _data = new byte[_recordLength]; try { Buffer.BlockCopy(previous.RecordData, 0, _data, 0, copy); Buffer.BlockCopy(pageDataRandomAccess.leBytes(_recordLength - copy), 0, _data, copy, (_recordLength - copy)); //We may have to check if we pulled enough bytes from the pageDataRA, incase we hit the end prematurely } catch (Exception ex) { throw new Exception("When reading " + (_recordLength - copy) + " bytes of TpsRecord"); } // buildHeader(); }
/// <summary> /// Gets data from the page /// If the page is compressed, it will uncompress it and return it. /// </summary> /// <returns></returns> private byte[] GetData() { //set our Randomaccess to the start of this page RandomAccess ra = RandomAccess.GetInstance(); byte[] pageData; ra.jumpAbs(addr); ra.jumpRelative(13); //skip the header //pull the page data //This really shouldn't be very big.. on my files it was about 8kb //If the file is using compression... uncompress it if ((pageSize != pageSizeUncompressed) && (flags == 0)) { try { pageData = ra.deRle(pageSize - 13); } catch (Exception ex) { throw new Exception("Bad RLE DataBlock ( compressed: " + pageSize + " uncompressed: " + pageSizeUncompressed + " Page Address: " + addr + "Record Count: " + recordCount.ToString() + "): ", ex); } } else { pageData = ra.leBytes(pageSize - 13); } return(pageData); }
public TPSRecord(ref RandomAccess pageDataRandomAccess) { _flags = pageDataRandomAccess.leByte(); if ((_flags & 0xC0) != 0xC0) { throw new Exception("Can't construct a TpsRecord without record lengths"); } _recordLength = pageDataRandomAccess.leShort(); _headerLength = pageDataRandomAccess.leShort(); _data = pageDataRandomAccess.leBytes(_recordLength); //read all of the data into a buffer. // buildHeader(); }
public object parseField(int type, int ofs, int len, TableField field, RandomAccess ra) { ra.jumpAbs(ofs); switch (type) { case 1: // byte assertEqual(1, len); return(ra.leByte()); case 2: // short assertEqual(2, len); return(ra.leShort()); case 3: // unsigned short assertEqual(2, len); return(ra.leUShort()); case 4: // Date, mask encoded. long date = ra.leULong(); if (date != 0) { long years = (date & 0xFFFF0000) >> 16; long months = (date & 0x0000FF00) >> 8; long days = (date & 0x000000FF); return(new DateTime((int)years, (int)months, (int)days)); } else { return(null); } case 5: // // Time, mask encoded. // So far i've only had values with hours and minutes // but no seconds or milliseconds so I've no way of // knowing how to decode these. // //TODO: Fix the time here based on decaseconds int time = ra.leLong(); int mins = (time & 0x00FF0000) >> 16; int hours = (time & 0x7F000000) >> 24; // return(hours + " " + mins); // case 6: // Long assertEqual(4, len); return(ra.leLong()); case 7: // Unsigned Long assertEqual(4, len); return(ra.leULong()); case 8: // Float assertEqual(4, len); return(ra.leFloat()); case 9: // Double assertEqual(8, len); return(ra.leDouble()); case 0x0A: // BCD encoded. return(ra.binaryCodedDecimal(len, field.BcdLengthOfElement, field.BcdDigitsAfterDecimalPoint)); case 0x12: // Fixed Length String return(ra.fixedLengthString(len)); case 0x13: return(ra.zeroTerminatedString()); case 0x14: return(ra.pascalString()); case 0x16: // Group (an overlay on top of existing data, can be anything). return(ra.leBytes(len)); default: throw new Exception("Unsupported type " + type + " (" + len + ")"); } }