Пример #1
0
        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;
            }
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        /// <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();
        }
Пример #5
0
        private long ofs;         //offset


        public static RandomAccess GetInstance()
        {
            if (_instance == null)
            {
                _instance = new RandomAccess();
            }
            return(_instance);
        }
Пример #6
0
        public void Open()
        {
            RandomAccess ra = RandomAccess.GetInstance();

            ra.OpenFile(_filename);


            _log += "INFO: Opened File: " + _filename;
        }
Пример #7
0
        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
        }
Пример #8
0
        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);
        }
Пример #9
0
        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();
        }
Пример #10
0
 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();
 }
Пример #11
0
        /// <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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        /// <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);
        }
Пример #14
0
 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();
     }
 }
Пример #15
0
        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));
        }
Пример #16
0
        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 + ")");
            }
        }
Пример #17
0
        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)));
        }
Пример #18
0
 public void Close()
 {
     RandomAccess.GetInstance().CloseFile();
 }