Пример #1
0
        /// <summary>
        /// Reads bytes until a unescaped closing parenthesis in found. Unescapes escaped parenthesis.
        /// Leaves reader on the char following the closing parenthesis.
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public static byte[] parseBinary(PsdBinaryReader r)
        {
            MemoryStream ms = new MemoryStream(128); //For writing the decoded binary
            byte         b  = 0;

            //Read bytes, keeping a two-byte shifting buffer so we can decode escaped chars.
            while (r.CanReadByte())
            {
                b = r.ReadByte();

                //Escaped parenthesis, skip slash
                if ((char)b == '\\')
                {
                    b = r.ReadByte();
                    ms.WriteByte(b);
                }
                else
                {
                    //We hit the end, an unescaped closng parenthesis.
                    if ((char)b == ')')
                    {
                        return(ms.ToArray());
                    }

                    ms.WriteByte(b);
                }
            }
            throw new TdTaParseException("Hit end of stream without finding closing parenthesis!");
        }
Пример #2
0
        /// <summary>
        /// Reads bytes until a unescaped closing parenthesis in found. Unescapes escaped parenthesis.
        /// Leaves reader on the char following the closing parenthesis.
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public static byte[] parseBinary(PsdBinaryReader r)
        {
            MemoryStream ms          = new MemoryStream(128); //For writing the decoded binary
            byte         b           = 0;
            byte         lastb       = 0;
            bool         hasLastByte = false;

            //Read bytes, keeping a two-byte shifting buffer so we can decode escaped chars.
            while (r.CanReadByte())
            {
                b = r.ReadByte();

                //Look for closing parenthesis
                if ((char)b == ')')
                {
                    if (hasLastByte && (char)lastb == '\\')
                    {
                        //Escaped parenthesis, skip slash
                        lastb       = 0;
                        hasLastByte = false;
                    }
                    else
                    {
                        //Unescaped closing parenthesis! We hit the end!
                        if (hasLastByte)
                        {
                            ms.WriteByte(lastb); //If we still have a byte in the buffer.
                        }
                        return(ms.ToArray());    //We hit the end, an unescaped closng parenthesis.
                    }
                }

                //Far as I know, nothing else is escaped.

                //Write lastb if present.
                if (hasLastByte)
                {
                    ms.WriteByte(lastb);
                }
                //Shift buffer
                lastb       = b;
                hasLastByte = true;
            }
            throw new TdTaParseException("Hit end of stream without finding closing parenthesis!");
        }
Пример #3
0
        /// <summary>
        /// Parses tdta contents into tokens. Throws a generic exception if unrecognized tokens are encountered
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public static Token nextToken(PsdBinaryReader r)
        {
            if (!r.CanReadByte())
            {
                return(null);
            }

            char c = r.ReadAsciiChars(1)[0];

            switch (c)
            {
            case '(': return(new Token(parseBinary(r)));                    //Binary data. Leading and trailing parens are stripped, and escaped parens are restored to normal.

            case '[': return(new Token(TokenType.StartList, c.ToString())); // [ opening list char

            case ']': return(new Token(TokenType.EndList, c.ToString()));   //Closing list char
            }
            //<< opening dict
            //>> closing dict
            if (c == '<' || c == '>')
            {
                char c2 = r.ReadAsciiChars(1)[0];
                if (c2 != c)
                {
                    throw new TdTaParseException("Unrecognized token: " + c + c2, r);
                }

                if (c == '<')
                {
                    return(new Token(TokenType.StartDict, "<<"));
                }
                else
                {
                    return(new Token(TokenType.EndDict, ">>"));
                }
            }
            //Dict key (Any non-whitespace, non-[]<> sequence allowed following forward slash)
            if (c == '/')
            {
                StringBuilder sb = new StringBuilder(40);
                while (r.CanReadByte())
                {
                    //Peek at the next char to see if it is whitespace
                    char pc = (char)r.PeekChar();
                    if (Char.IsWhiteSpace(pc) || pc == '\n' || pc == '[' || pc == ']' || pc == '<' || pc == '>')
                    {
                        //We're done.
                        //Strip the leading slash, create token with name
                        return(new Token(TokenType.MapKey, sb.ToString()));
                    }
                    else
                    {
                        //A valid char, append it.
                        sb.Append(r.ReadChar());
                    }
                }
            }
            //Integer or double. Ends at whitespace, newline, ], or >
            if (Char.IsDigit(c) || c == '-' || c == '.')
            {
                StringBuilder sb = new StringBuilder(40);
                sb.Append(c);
                while (r.CanReadByte())
                {
                    //Peek at the next char to see if it is whitespace
                    char pc = (char)r.PeekChar();
                    if (Char.IsWhiteSpace(pc) || pc == '\n' || pc == ']' || pc == '>')
                    {
                        //We're done. Find out what kind of number it is.
                        string s = sb.ToString();
                        //If it has a decimal, it's a double
                        if (s.Contains('.'))
                        {
                            return(new Token(TokenType.Double, double.Parse(s, floatingPointStyle, NumberFormatInfo.InvariantInfo)));
                        }
                        else
                        {
                            return(new Token(TokenType.Integer, int.Parse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo)));
                        }
                    }
                    else if (Char.IsDigit(c) || c == '-' || c == '.')
                    {
                        //A valid char, append it.
                        sb.Append(r.ReadChar());
                    }
                    else
                    {
                        //Unrecognized char in numeric sq
                        throw new TdTaParseException("Unrecognized character in numeric sequence: " + sb.ToString() + pc, r);
                    }
                }
            }
            //Boolean (true|false) parsing
            if (c == 't' || c == 'T' || c == 'f' || c == 'F')
            {
                string s  = c.ToString() + r.ReadChar().ToString() + r.ReadChar().ToString() + r.ReadChar().ToString();
                char   pc = (char)r.PeekChar();
                if (s.Equals("true", StringComparison.OrdinalIgnoreCase))
                {
                    return(new Token(TokenType.Boolean, true));
                }
                else if (s.Equals("fals", StringComparison.OrdinalIgnoreCase) && (pc == 'e' || pc == 'E'))
                {
                    r.ReadChar(); //discard 'e'
                    return(new Token(TokenType.Boolean, false));
                }
                else
                {
                    throw new TdTaParseException("Unrecognized boolean value: " + s + pc, r);
                }
            }
            //Whitespace parsing
            if (Char.IsWhiteSpace(c) || c == '\n')
            {
                StringBuilder sb = new StringBuilder(40);
                sb.Append(c);
                while (r.CanReadByte())
                {
                    //Peek at the next char to see if it is whitespace
                    char pc = (char)r.PeekChar();
                    if (Char.IsWhiteSpace(pc) || pc == '\n')
                    {
                        sb.Append(r.ReadChar());
                    }
                    else
                    {
                        //We done.
                        break;
                    }
                }
                return(new Token(TokenType.Whitespace, sb.ToString()));
            }
            throw new TdTaParseException("Unrecognized token: " + c, r);
        }