Package org.apache.sanselan.common

Source Code of org.apache.sanselan.common.BasicCParser

/*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*  under the License.
*/

package org.apache.sanselan.common;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.Map;
import org.apache.sanselan.ImageReadException;

public class BasicCParser
{
    private PushbackInputStream is;

    public BasicCParser(ByteArrayInputStream is)
    {
        this.is = new PushbackInputStream(is);
    }

    public String nextToken() throws IOException, ImageReadException
    {
        // I don't know how complete the C parsing in an XPM file
        // is meant to be, this is just the very basics...

        boolean inString = false;
        boolean inIdentifier = false;
        boolean hadBackSlash = false;
        StringBuilder token = new StringBuilder();
        for (int c = is.read(); c != -1; c = is.read())
        {
            if (inString)
            {
                if (c == '\\')
                {
                    token.append('\\');
                    hadBackSlash = !hadBackSlash;
                }
                else if (c == '"')
                {
                    token.append('"');
                    if (!hadBackSlash)
                        return token.toString();
                    hadBackSlash = false;
                }
                else if (c == '\r' || c == '\n')
                    throw new ImageReadException("Unterminated string in XPM file");
                else
                {
                    token.append((char)c);
                    hadBackSlash = false;
                }
            }
            else if (inIdentifier)
            {
                if (Character.isLetterOrDigit(c) || c == '_')
                    token.append((char)c);
                else
                {
                    is.unread(c);
                    return token.toString();
                }
            }
            else
            {
                if (c == '"')
                {
                    token.append('"');
                    inString = true;
                }
                else if (Character.isLetterOrDigit(c) || c == '_')
                {
                    token.append((char)c);
                    inIdentifier = true;
                }
                else if (c == '{' || c == '}' ||
                        c == '[' || c == ']' ||
                        c == '*' || c == ';' ||
                        c == '=' || c == ',')
                {
                    token.append((char)c);
                    return token.toString();
                }
                else if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
                    ;
                else
                    throw new ImageReadException("Unhandled/invalid character '" +
                            ((char)c) + "' found in XPM file");
            }
        }

        if (inIdentifier)
            return token.toString();
        if (inString)
            throw new ImageReadException("Unterminated string ends XMP file");
        return null;
    }

    public static ByteArrayOutputStream preprocess(InputStream is,
            StringBuilder firstComment, Map defines)
            throws IOException, ImageReadException
    {
        boolean inString = false;
        boolean inComment = false;
        boolean inDirective = false;
        boolean hadSlash = false;
        boolean hadStar = false;
        boolean hadBackSlash = false;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        boolean seenFirstComment = (firstComment == null);
        StringBuilder directiveBuffer = new StringBuilder();
        for (int c = is.read(); c != -1; c = is.read())
        {
            if (inComment)
            {
                if (c == '*')
                {
                    if (hadStar && !seenFirstComment)
                        firstComment.append('*');
                    hadStar = true;
                }
                else if(c == '/')
                {
                    if (hadStar)
                    {
                        hadStar = false;
                        inComment = false;
                        seenFirstComment = true;
                    }
                    else
                        out.write(c);
                }
                else
                {
                    if (hadStar && !seenFirstComment)
                        firstComment.append('*');
                    hadStar = false;
                    if (!seenFirstComment)
                        firstComment.append((char)c);
                }
            }
            else if (inString)
            {
                if (c == '\\')
                {
                    if (hadBackSlash)
                        out.write('\\');
                    hadBackSlash = true;
                }
                else if (c == '"')
                {
                    if (hadBackSlash)
                    {
                        out.write('\\');
                        hadBackSlash = false;
                    }
                    else
                        inString = false;
                    out.write('"');
                }
                else if (c == '\r' || c == '\n')
                    throw new ImageReadException("Unterminated string in file");
                else
                {
                    if (hadBackSlash)
                    {
                        out.write('\\');
                        hadBackSlash = false;
                    }
                    out.write(c);
                }
            }
            else if (inDirective)
            {
                if (c == '\r' || c == '\n')
                {
                    inDirective = false;
                    String[] tokens = tokenizeRow(directiveBuffer.toString());
                    if (tokens.length < 2 || tokens.length > 3)
                        throw new ImageReadException("Bad preprocessor directive");
                    if (!tokens[0].equals("define"))
                        throw new ImageReadException("Invalid/unsupported " +
                                "preprocessor directive '" + tokens[0] + "'");
                    defines.put(tokens[1], (tokens.length == 3) ? tokens[2] : null);
                    directiveBuffer.setLength(0);
                }
                else
                    directiveBuffer.append((char)c);
            }
            else
            {
                if (c == '/')
                {
                    if (hadSlash)
                        out.write('/');
                    hadSlash = true;
                }
                else if (c == '*')
                {
                    if (hadSlash)
                    {
                        inComment = true;
                        hadSlash = false;
                    }
                    else
                        out.write(c);
                }
                else if (c == '"')
                {
                    if (hadSlash)
                        out.write('/');
                    hadSlash = false;
                    out.write(c);
                    inString = true;
                }
                else if (c == '#')
                {
                    if (defines == null)
                        throw new ImageReadException("Unexpected preprocessor directive");
                    inDirective = true;
                }
                else
                {
                    if (hadSlash)
                        out.write('/');
                    hadSlash = false;
                    out.write(c);
                    // Only whitespace allowed before first comment:
                    if (c != ' ' && c != '\t' && c != '\r' && c != '\n')
                        seenFirstComment = true;
                }
            }
        }
        if (hadSlash)
            out.write('/');
        if (hadStar)
            out.write('*');
        if (inString)
            throw new ImageReadException("Unterminated string at the end of file");
        if (inComment)
            throw new ImageReadException("Unterminated comment at the end of file");
        return out;
    }

    public static String[] tokenizeRow(String row)
            throws ImageReadException
    {
        String[] tokens = row.split("[ \t]");
        int numLiveTokens = 0;
        for (int i = 0; i < tokens.length; i++)
        {
            if (tokens[i] != null && tokens[i].length() > 0)
                ++numLiveTokens;
        }
        String[] liveTokens = new String[numLiveTokens];
        int next = 0;
        for (int i = 0; i < tokens.length; i++)
        {
            if (tokens[i] != null && tokens[i].length() > 0)
                liveTokens[next++] = tokens[i];
        }
        return liveTokens;
    }

    public static void unescapeString(StringBuilder stringBuilder, String string)
            throws ImageReadException
    {
        if (string.length() < 2)
            throw new ImageReadException("Parsing XPM file failed, " +
                    "string is too short");
        if (string.charAt(0) != '"' || string.charAt(string.length() - 1) != '"')
            throw new ImageReadException("Parsing XPM file failed, " +
                    "string not surrounded by '\"'");
        boolean hadBackSlash = false;
        for (int i = 1; i < (string.length() - 1); i++)
        {
            char c = string.charAt(i);
            if (hadBackSlash)
            {
                if (c == '\\')
                    stringBuilder.append('\\');
                else if (c == '"')
                    stringBuilder.append('"');
                else if (c == '\'')
                    stringBuilder.append('\'');
                else if (c == 'x')
                {
                    if (i + 2 >= string.length())
                        throw new ImageReadException("Parsing XPM file failed, " +
                                "hex constant in string too short");
                    char hex1 = string.charAt(i + 1);
                    char hex2 = string.charAt(i + 2);
                    i += 2;
                    int constant;
                    try
                    {
                        constant =  Integer.parseInt("" + hex1 + hex2, 16);
                    }
                    catch (NumberFormatException nfe)
                    {
                        throw new ImageReadException("Parsing XPM file failed, " +
                                "hex constant invalid", nfe);
                    }
                    stringBuilder.append((char)constant);
                }
                else if (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' ||
                        c == '5' || c == '6' || c == '7')
                {
                    int length = 1;
                    if (i+1 < string.length() && '0' <= string.charAt(i+1) &&
                            string.charAt(i+1) <= '7')
                        ++length;
                    if (i+2 < string.length() && '0' <= string.charAt(i+2) &&
                            string.charAt(i+2) <= '7')
                        ++length;
                    int constant = 0;
                    for (int j = 0; j < length; j++)
                    {
                        constant *= 8;
                        constant += (string.charAt(i + j) - '0');
                    }
                    i += length - 1;
                    stringBuilder.append((char)constant);
                }
                else if (c == 'a')
                    stringBuilder.append((char)0x07);
                else if (c == 'b')
                    stringBuilder.append((char)0x08);
                else if (c == 'f')
                    stringBuilder.append((char)0x0c);
                else if (c == 'n')
                    stringBuilder.append((char)0x0a);
                else if (c == 'r')
                    stringBuilder.append((char)0x0d);
                else if (c == 't')
                    stringBuilder.append((char)0x09);
                else if (c == 'v')
                    stringBuilder.append((char)0x0b);
                else
                    throw new ImageReadException("Parsing XPM file failed, " +
                            "invalid escape sequence");
                hadBackSlash = false;
            }
            else
            {
                if (c == '\\')
                    hadBackSlash = true;
                else if (c == '"')
                    throw new ImageReadException("Parsing XPM file failed, " +
                            "extra '\"' found in string");
                else
                    stringBuilder.append(c);
            }
        }
        if (hadBackSlash)
            throw new ImageReadException("Parsing XPM file failed, " +
                    "unterminated escape sequence found in string");
    }
}
TOP

Related Classes of org.apache.sanselan.common.BasicCParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.