public TableField(ref RandomAccess ra) { _fieldType = ra.leByte(); _offset = ra.leShort(); _fieldName = ra.zeroTerminatedString(); //remove the table name from the start if it is there if (_fieldName.IndexOf(':') > 0) { _fieldName = _fieldName.Substring(_fieldName.IndexOf(':') + 1); } _elements = ra.leShort(); _length = ra.leShort(); _flags = ra.leShort(); _index = ra.leShort(); switch (_fieldType) { case 0x0a: _bcdDigitsAfterDecimalPoint = ra.leByte(); _bcdLengthOfElement = ra.leByte(); break; case 0x12: case 0x13: case 0x14: _stringLength = ra.leShort(); _stringMask = ra.zeroTerminatedString(); if (_stringMask.Length == 0) { ra.leByte(); } break; } }
/// <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); }
/// <summary> /// Will read the very top head of the TPS file. /// It will also fill in the block info list /// </summary> /// <returns></returns> private bool ReadTPSHeaderInfo() { _tpsHeader = new TPSHeader(); _tpsHeader.Process(); //fill in our blocks _tpsBlocks = new List <TPSBlock>(); long tpsFilelength = RandomAccess.GetInstance().fileSize; for (int t = 0; t < _tpsHeader.PageStart.Length; t++) { int ofs = _tpsHeader.PageStart[t]; int end = _tpsHeader.PageEnd[t]; // Skips the first entry (0 length) and any blocks that are beyond // the file size. if (((ofs == 0x0200) && (end == 0x200)) || (ofs >= tpsFilelength)) { continue; } else { _tpsBlocks.Add(new TPSBlock(ofs, end)); } } return(true); }
/// <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(); }
private long ofs; //offset public static RandomAccess GetInstance() { if (_instance == null) { _instance = new RandomAccess(); } return(_instance); }
public void Open() { RandomAccess ra = RandomAccess.GetInstance(); ra.OpenFile(_filename); _log += "INFO: Opened File: " + _filename; }
public void Process() { RandomAccess ra = RandomAccess.GetInstance(); addr = ra.leLong(); pageSize = ra.leShort(); pageSizeUncompressed = ra.leShort(); pageSizeUncompressedWithoutHeader = ra.leShort(); recordCount = ra.leShort(); flags = (int)ra.leByte(); ra.jumpRelative(pageSize - 13); //burn these bytes. This will leave the RandomAccess at the very end of the page }
public override string ToString() { RandomAccess ra = RandomAccess.GetInstance(); string str = ""; str += "TpsHeader(" + ra.toHex8(Addr) + "," + ra.toHex4(HeaderSize) + "," + ra.toHex8(FileLength1) + "," + ra.toHex8(FileLength2) + "," + TopSpeed + "," + ra.toHex4(Zeros) + "," + ra.toHex8(LastIssuedRow) + "," + ra.toHex8(Changes) + "," + ra.toHex8(ManagementPageRef) + ")\n"; for (int t = 0; t < PageStart.Length; t++) { str += ra.toHex8(PageStart[t]) + ".." + ra.toHex8(PageEnd[t]) + "\n"; } return(str); }
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 TableMemo(ref RandomAccess ra) { _externalFile = ra.zeroTerminatedString(); if (_externalFile.Length == 0) { if (ra.leByte() != 1) { throw new Exception("Bad Memo Definition, missing 0x01 after zero string:" + _externalFile); } } _name = ra.zeroTerminatedString(); _length = ra.leShort(); _flags = ra.leShort(); }
/// <summary> /// Will return a list of all pages in the block /// </summary> /// <returns></returns> public List <TPSPage> getPages() { RandomAccess ra = RandomAccess.GetInstance(); List <TPSPage> pages = new List <TPSPage>(); ra.jumpAbs(_start); //jump to the start of the block try{ while (ra.position < _end) //while we have not fallen off the end of the file { TPSPage page = new TPSPage(); page.Process(); pages.Add(page); //pages always start on the position % 100 = 0 //So let's jump forward to find the next start if ((ra.position & 0xFF) != 0x00) { ra.jumpAbs((ra.position & 0xFFFFFF00L) + 0x0100); } //we can find the next page because the address of the page will be in the data int addr = 0; if (!ra.isAtEnd()) { do { addr = ra.leLong(); ra.jumpRelative(-4); //backup 4 bytes if (addr != ra.position) { ra.jumpRelative(0x0100); } }while ((addr != ra.position) && !ra.isAtEnd()); } } }catch (Exception ex) { ; } return(pages); }
public bool ProcessTableDefinitionData(int tableID, byte[] defintionData) { _id = tableID; _fields = new List <TableField>(); _memos = new List <TableMemo>(); _indexes = new List <TableIndex>(); RandomAccess ra = new RandomAccess(); ra.OpenStream(new System.IO.MemoryStream(defintionData)); _driverVersion = ra.leShort(); _recordLength = ra.leShort(); _noOfFields = ra.leShort(); _noOfMemos = ra.leShort(); _noOfIndexes = ra.leShort(); try { for (int t = 0; t < _noOfFields; t++) { _fields.Add(new TableField(ref ra)); } for (int t = 0; t < _noOfMemos; t++) { _memos.Add(new TableMemo(ref ra)); } for (int t = 0; t < _noOfIndexes; t++) { _indexes.Add(new TableIndex(ref ra)); } } catch (Exception ex) { throw new Exception("Bad Table Definition ", ex); } ra = null; _tableDT = BuildEmptyDataTable(); return(true); }
/// <summary> /// Returns all records of the page /// <returns></returns> public List <TPSRecord> GetRecords() { List <TPSRecord> records = new List <TPSRecord>(); byte[] pageData = GetData(); //go through each record in the page RandomAccess ra = new RandomAccess(); ra.OpenStream(new MemoryStream(pageData)); records.Clear(); // Skip pages with non 0x00 flags as they don't seem to contain TpsRecords. if (flags == 0x00) { //data.pushPosition(); try { TPSRecord prev = null; do { TPSRecord current = null; if (prev == null) { current = new TPSRecord(ref ra); } else { current = new TPSRecord(ref prev, ref ra); } records.Add(current); prev = current; } while (!ra.isAtEnd() && records.Count < recordCount); } finally { //data.popPosition(); } } return(records); }
public TableIndex(ref RandomAccess ra) { _externalFile = ra.zeroTerminatedString(); if (_externalFile.Length == 0) { int read = ra.leByte(); if (read != 1) { throw new Exception("Bad Index Definition, missing 0x01 after zero string (" + ra.toHex2(read) + ")"); } } _name = ra.zeroTerminatedString(); _flags = ra.leByte(); _fieldsInKey = ra.leShort(); _keyField = new int[_fieldsInKey]; _keyFieldFlag = new int[_fieldsInKey]; for (int t = 0; t < _fieldsInKey; t++) { _keyField[t] = ra.leShort(); _keyFieldFlag[t] = ra.leShort(); } }
public void Process() { RandomAccess ra = RandomAccess.GetInstance(); ra.position = 0; Addr = ra.leLong(); if (Addr != 0) { throw new Exception("File doesn't start with 0x00000000 - it's not a TPS databse"); } HeaderSize = ra.leShort(); FileLength1 = ra.leLong(); FileLength2 = ra.leLong(); TopSpeed = ra.fixedLengthString(4); Zeros = ra.leShort(); LastIssuedRow = ra.beLong(); Changes = ra.leLong(); ManagementPageRef = ra.toFileOffset(ra.leLong()); PageStart = ra.toFileOffset(ra.leLongArray((0x110 - 0x20) / 4)); PageEnd = ra.toFileOffset(ra.leLongArray((0x200 - 0x110) / 4)); }
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 + ")"); } }
public override string ToString() { RandomAccess ra = RandomAccess.GetInstance(); return(string.Format("[TPSPage Addr={0}, PageSize={1}, PageSizeUncompressed={2}, PageSizeUncompressedWithoutHeader={3}, RecordCount={4}, Flags={5}]", ra.toHex8(addr), ra.toHex4(pageSize), ra.toHex4(pageSizeUncompressed), ra.toHex4(pageSizeUncompressedWithoutHeader), ra.toHex4(recordCount), ra.toHex2(flags))); }
public void Close() { RandomAccess.GetInstance().CloseFile(); }