Ejemplo n.º 1
0
        public List <TokenXRefEntry> ParseXRef()
        {
            Tokenizer.IgnoreComments = true;
            TokenObject  t       = Tokenizer.GetToken();
            TokenKeyword keyword = t as TokenKeyword;

            if ((keyword == null) || (keyword.Value != ParseKeyword.XRef))
            {
                // Scan entire source creating XRef entries for each indirect object
                return(IndirectObjectsToXRef());
            }
            else
            {
                List <TokenXRefEntry> entries = new List <TokenXRefEntry>();
                ParseXRefSections(entries);
                return(entries);
            }
        }
Ejemplo n.º 2
0
        public List <TokenXRefEntry> IndirectObjectsToXRef()
        {
            List <TokenXRefEntry> entries = new List <TokenXRefEntry>();

            // Start scanning from beginning of the source
            Tokenizer.IgnoreComments = false;
            Tokenizer.Position       = 0;

            long lastTrailer = -1;

            do
            {
                long        t1Position = Tokenizer.Position;
                TokenObject t1         = Tokenizer.GetToken();
                if (t1 is TokenInteger)
                {
                    TokenInteger t2 = Tokenizer.GetToken() as TokenInteger;
                    if (t2 != null)
                    {
                        TokenKeyword t3 = Tokenizer.GetToken() as TokenKeyword;
                        if ((t3 != null) && (t3.Value == ParseKeyword.Obj))
                        {
                            TokenInteger id = (TokenInteger)t1;
                            entries.Add(new TokenXRefEntry(id.Value, t2.Value, t1Position, true));
                        }
                    }
                }
                else if ((t1 is TokenKeyword) && ((TokenKeyword)t1).Value == ParseKeyword.Trailer)
                {
                    lastTrailer = t1Position;
                }
            } while (Tokenizer.GotoNextLine());

            // Leave with the position on the last 'trailer' as caller will then parse it
            if (lastTrailer >= 0)
            {
                Tokenizer.Position = lastTrailer;
            }

            return(entries);
        }
Ejemplo n.º 3
0
        private TokenObject GetKeywordOrIdentifier()
        {
            long position = _position + _index;

            // Scan looking for the end of the keyword characters
            int key = _index;

            while ((key < _length) && _lookupKeyword[_line[key]])
            {
                key++;
            }

            string       text  = Encoding.ASCII.GetString(_line, _index, key - _index);
            TokenKeyword token = TokenKeyword.GetToken(text);

            if (token != null)
            {
                _index = key;
                return(token);
            }

            if (AllowIdentifiers)
            {
                // Scan looking for the end of the identifier
                key = _index;
                while ((key < _length) && !_lookupDelimiterWhitespace[_line[key]])
                {
                    key++;
                }

                text   = Encoding.ASCII.GetString(_line, _index, key - _index);
                _index = key;

                return(new TokenIdentifier(text));
            }
            else
            {
                return(new TokenError(position, $"Cannot parse '{text}' as a keyword."));
            }
        }
Ejemplo n.º 4
0
        public ParseIndirectObject ParseIndirectObject()
        {
            Tokenizer.IgnoreComments = true;
            TokenObject t = Tokenizer.GetToken();

            ThrowOnEmptyOrError(t);

            // Indirect object starts with an integer, the object identifier
            if (!(t is TokenInteger))
            {
                Tokenizer.PushToken(t);
                return(null);
            }

            // Second is another integer, the generation number
            TokenObject u = Tokenizer.GetToken();

            ThrowOnEmptyOrError(u);

            if (!(u is TokenInteger))
            {
                Tokenizer.PushToken(t);
                Tokenizer.PushToken(u);
                return(null);
            }

            // This is the keyword 'obj'
            TokenObject v = Tokenizer.GetToken();

            ThrowOnEmptyOrError(v);
            if (!(v is TokenKeyword) || ((v as TokenKeyword).Value != ParseKeyword.Obj))
            {
                Tokenizer.PushToken(t);
                Tokenizer.PushToken(u);
                Tokenizer.PushToken(v);
                return(null);
            }

            // Get actual object that is the content
            ParseObjectBase obj = ParseObject();

            if (obj == null)
            {
                throw new ApplicationException($"Indirect object has missing content.");
            }

            // Must be followed by either 'endobj' or 'stream'
            v = Tokenizer.GetToken();
            ThrowOnEmptyOrError(v);

            TokenKeyword keyword = v as TokenKeyword;

            if (keyword == null)
            {
                // PH: FIXME:
                //throw new ApplicationException($"Indirect object has missing 'endobj or 'stream'.");
                return(new ParseIndirectObject(t as TokenInteger, u as TokenInteger, new ParseInteger(0)));
            }

            if (keyword.Value == ParseKeyword.EndObj)
            {
                return(new ParseIndirectObject(t as TokenInteger, u as TokenInteger, obj));
            }
            else if (keyword.Value == ParseKeyword.Stream)
            {
                ParseDictionary dictionary = obj as ParseDictionary;
                if (dictionary == null)
                {
                    throw new ApplicationException($"Stream must be preceded by a dictionary.");
                }

                if (!dictionary.ContainsName("Length"))
                {
                    throw new ApplicationException($"Stream dictionary must contain a 'Length' entry.");
                }

                ParseObjectBase lengthObj = dictionary["Length"];

                // Resolve any object reference
                ParseObjectReference reference = lengthObj as ParseObjectReference;
                if (reference != null)
                {
                    lengthObj = OnResolveReference(reference);
                }

                ParseInteger length = lengthObj as ParseInteger;
                if (length == null)
                {
                    throw new ApplicationException($"Stream dictionary has a 'Length' entry that is not an integer entry.");
                }

                if (length.Value < 0)
                {
                    throw new ApplicationException($"Stream dictionary has a 'Length' less than 0.");
                }

                byte[] bytes = Tokenizer.GetBytes(length.Value);
                if (bytes == null)
                {
                    throw new ApplicationException($"Cannot read in expected {length.Value} bytes from stream.");
                }

                // Stream contents must be followed by 'endstream'
                v = Tokenizer.GetToken();
                ThrowOnEmptyOrError(v);

                keyword = v as TokenKeyword;
                if (keyword == null)
                {
                    throw new ApplicationException($"Stream has missing 'endstream' after content.");
                }

                if (keyword.Value != ParseKeyword.EndStream)
                {
                    throw new ApplicationException($"Stream has unexpected keyword {keyword.Value} instead of 'endstream'.");
                }

                // Stream contents must be followed by 'endobj'
                v = Tokenizer.GetToken();
                ThrowOnEmptyOrError(v);

                keyword = v as TokenKeyword;
                if (keyword == null)
                {
                    throw new ApplicationException($"Indirect object has missing 'endobj'.");
                }

                if (keyword.Value != ParseKeyword.EndObj)
                {
                    throw new ApplicationException($"Indirect object has unexpected keyword {keyword.Value} instead of 'endobj'.");
                }

                return(new ParseIndirectObject(t as TokenInteger, u as TokenInteger, new ParseStream(dictionary, bytes)));
            }
            else
            {
                throw new ApplicationException($"Indirect object has unexpected keyword {keyword.Value}.");
            }
        }