public void Parse(string path)
        {
            rootPath = Path.GetDirectoryName(path);
            DataBlock dataBlock = new DataBlock(path);

            // separa en bloques los datos de cada entidad...
            Dictionary<string, DataBlock> dataParts = SplitDataBlocks(dataBlock, db.entityNames);

            db.Entities.AddRange(ParseEntities(null, db.entityNames, dataParts));
        }
        public void ParseEntities(string path)
        {
            List<List<Entity>> candidates = new List<List<Entity>>();

            List<Entity> entitiesNames;
            DataBlock dataBlock = new DataBlock(path);

            // hace la hipótesis de que es una entidad...
            for (int i = 0; i < dataBlock.data.Length; i++)
            {
                dataBlock.n = i;
                entitiesNames = new List<Entity>();
                TryEntities(dataBlock, "", entitiesNames);
                if (entitiesNames.Count > 0)
                    candidates.Add(entitiesNames);
            }
            db.entityNames = GetBest(candidates);
        }
        public Entity ParseEntity(DataBlock dataBlock, string entity, string parent)
        {
            var e = new Entity();
            e.rootPath = rootPath;
            // construye el encabezado esperable
            var block = dataBlock.makeStringBlock(entity);
            var blockParent = dataBlock.makeStringBlock(parent);
            byte[] full;
            if (parent != "")
                full = dataBlock.addArrays(block, block, blockParent);
            else
                full = dataBlock.addArrays(block, blockParent);

            if (dataBlock.moveTo(full) == false)
                throw new Exception("Sequence not found.");
            // lee la entidad
            e.Name = dataBlock.eatShortString();
            e.RelationChild = dataBlock.eatShortString();
            if (e.RelationChild != "")
                e.RelationParent = dataBlock.eatShortString();
            e.Description = dataBlock.eatShortString();
            e.IndexFilename = dataBlock.eatShortString();
            e.s1 = dataBlock.eat16int();
            if (e.IndexFilename != "")
            {
                e.CodesVariable = dataBlock.eatShortString();
                e.LabelVariable = dataBlock.eatShortString();
                e.Level = dataBlock.eat32int();
                e.b1 = dataBlock.eatByte();
                //e.VariableCount = no es confiable...que guarde rangos... eat32int();
                // en base al count de variables, que busque los "dataset"
                while (true)
                {
                    Variable v = ParseVariable(dataBlock, e);
                    if (v != null)
                        e.Variables.Add(v);
                    else
                        break;
                }
            }
            e.VariableCount = e.Variables.Count;
            return e;
        }
 private bool checkEntityStart(DataBlock dataBlock)
 {
     string relationChild;
     string name = dataBlock.eatShortString();
     if (dataBlock.eatPlausibleString(out relationChild) == false)
         return false;
     if (relationChild != "")
     {
     //		if (eatPlausibleString(out relationParent) == false)
     //		return false;
     }
     string description;
     string indexfilename;
     if (dataBlock.eatPlausibleString(out description, false) == false)
         return false;
     if (dataBlock.eatPlausibleString(out indexfilename, false) == false)
         return false;
     return description.EndsWith(".ptr") ||
         indexfilename.EndsWith(".ptr");
 }
        private Dictionary<string, DataBlock> SplitDataBlocks(DataBlock dataBlock, List<Entity> entitiesNames)
        {
            Dictionary<string, DataBlock> dataParts = new Dictionary<string, DataBlock>();

            int prevStart = -1;
            int iStart = 0;
            List<Tuple<string, string>> linealEntityParentNames = Entity.Linealize(null, entitiesNames);
            for (int i = 0; i < linealEntityParentNames.Count; i++)
            {
                string entity = linealEntityParentNames[i].Item2;
                iStart = ParseBeginning(dataBlock, linealEntityParentNames[i].Item2,
                                                                                        linealEntityParentNames[i].Item1);
                if (prevStart != -1)
                {
                    dataParts[linealEntityParentNames[i - 1].Item2] = dataBlock.getPart(prevStart, iStart);
                }
                prevStart = iStart;
            }
            // guarda el último
            iStart = dataBlock.data.Length;
            dataParts[linealEntityParentNames[linealEntityParentNames.Count - 1].Item2] = dataBlock.getPart(prevStart, iStart);
            return dataParts;
        }
        private Variable ParseVariable(DataBlock dataBlock, Entity e)
        {
            // lee las variables
            if (JumptToDataSet(dataBlock) == false)
                return null;
            Variable v = new Variable(e);
            v.Name = dataBlock.eatShortString();
            v.Declaration = dataBlock.eatShortString();
            v.Filter = dataBlock.eatShortString();
            v.Range = dataBlock.eatShortString();
            v.Type = dataBlock.eatShortString();
            v.ValuesLabelsRaw = dataBlock.eatShortString();
            v.Label = dataBlock.eatShortString();
            v.Group = dataBlock.eatShortString();

            v.ParseDeclaration();
            v.ParseValueLabels();
            v.ParseMissingAndPrecision();
            return v;
        }
        private int ParseBeginning(DataBlock dataBlock, string entity, string parent)
        {
            var e = new Entity();
            e.rootPath = rootPath;
            // construye el encabezado esperable
            var block = dataBlock.makeStringBlock(entity);
            var blockParent = dataBlock.makeStringBlock(parent);
            byte[] full;
            if (parent != "")
                full = dataBlock.addArrays(block, block, blockParent);
            else
                full = dataBlock.addArrays(block, blockParent);

            if (dataBlock.moveTo(full) == false)
                throw new Exception("Sequence not found.");
            return dataBlock.n;
        }
 private bool JumptToDataSet(DataBlock dataBlock)
 {
     if (dataBlock.moveTo("DATASET") == false)
         return false;
     // valida el tipo de dato
     if (checkDataType(dataBlock) == false)
             return false;
         //
     dataBlock.move(-2);
     // retrocede para leer el nombre
     if (dataBlock.moveBackString(32) < 1)
     {
         dataBlock.move(6);
         // este no es válido... busca si hay más...
         return JumptToDataSet(dataBlock);
     }
     else
         return true;
 }
 private bool checkDataType(DataBlock dataBlock)
 {
     dataBlock.move(8); // "DATASET "
         if (dataBlock.n + 3 > dataBlock.data.Length)
                 return false;
         string type = dataBlock.eatChars(3); // "DBL", "LNG", etc
         if (new List<string>(validTypes).Contains(type) == false)
         {
                 // este no es válido... busca si hay más...
                 return JumptToDataSet(dataBlock);
         }
         // retrocede hasta el inicio de DATASET
         dataBlock.move(-11);
         return true;
 }
        private void ProcessOcurrence(DataBlock dataBlock, List<Entity> leaves, List<Entity> entitiesNames)
        {
            if (dataBlock.moveBackString() == -1)
                return;

            int keepN = dataBlock.n;
            string child = dataBlock.eatShortString();
            dataBlock.n = keepN;
            if (entitiesNames.Count > 0 && entitiesNames[entitiesNames.Count - 1].Name == child)
                return;
            if (dataBlock.IsText(child) == false || child == "") return;
            // avanzó ok...
            List<Entity> names = new List<Entity>();
            TryEntities(dataBlock, child, names);
            if (names.Count > 0)
                leaves.AddRange(names);
        }
        private void TryEntities(DataBlock dataBlock, string parent, List<Entity> entitiesNames)
        {
            // lee el length
            string entityNameString;
            if (dataBlock.PlausibleString(out entityNameString) == false || entityNameString  == "")
                return;
            //
            if (checkEntityStart(dataBlock) == false)
                return;
            Entity entity = new Entity() { Name = entityNameString };
            entitiesNames.Add(entity);
            // ahora se va a buscar a sus hijos
            var block = dataBlock.makeStringBlock(entityNameString);
            List<Entity> variants = new List<Entity>();
            List<int> allBlockOccurrences = dataBlock.GetAllMatches(block);

            foreach (int startN in allBlockOccurrences)
            {
                dataBlock.n = startN;
                ProcessOcurrence(dataBlock, variants, entity.Children);
            }
            if (variants.Count > 0)
            {
                entity.Children.Clear();
                entity.Children.AddRange(variants);
            }
        }