All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.darkmist.alib.str.Escape Maven / Gradle / Ivy

/*
 *  Copyright (C) 2012 Ed Schaller 
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package net.darkmist.alib.str;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Escape
{
	private static final char DEFAULT_ESCAPE = '\\';
	private static final boolean DEFAULT_IGNORE_ERROR = true;
	private static final char[] EMPTY_CHAR_ARRAY = new char[0];
	private static final String[] EMPTY_STRING_ARRAY = new String[0];

	public static Appendable unescape(CharSequence src, Appendable dst, char escapeChar, boolean ignoreError) throws IOException, EscapeException
	{
		int srcLen = src.length();
		char ch;		// char from src we're looking at
		int left = srcLen;	// amount left in src
		int i;

		srcloop: for(i=0;i=srcLen)
				if(ignoreError)
					return dst;
				else
					throw new EscapeException("String to escape ends in unescaped escape char.");
			ch=src.charAt(i);
			switch(ch)
			{
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
					// octal bleh...
					left = srcLen - i;

					// check for just one octal
					if(!(left>=2 && Octal.isOctal(src.charAt(i+1))))
					{	// only one octal
						dst.append((char)Octal.unoctByte(src,i,1));
						continue srcloop;
					}

					// check for two octals
					if(!(left>=3 && Octal.isOctal(src.charAt(i+2))))
					{	// two octal chars
						dst.append((char)Octal.unoctByte(src,i,2));
						i++;
						continue srcloop;
					}

					// three octal chars (ha ha ha)
					//System.err.println("escaped=" + src.subSequence(i,i+3));
					dst.append((char)Octal.unoctShort(src,i,3));
					i+=2;
					continue srcloop;
				case 'a':
					dst.append('\u0007');
					continue srcloop;
				case 'b':
					dst.append('\b');
					continue srcloop;
				case 't':
					dst.append('\t');
					continue srcloop;
				case 'n':
					dst.append('\n');
					continue srcloop;
				case 'v':
					dst.append('\u000b');
					continue srcloop;
				case 'f':
					dst.append('\f');
					continue srcloop;
				case 'r':
					dst.append('\r');
					continue srcloop;
				case 'x':
				case 'X':
					// hex escape
					if(srcLen - i < 3)
						if(ignoreError)
							return dst;
						else
							throw new EscapeException("String to escape ends in truncated hex escape");
					i++;
					dst.append((char)(Hex.unhexByte(src,i,2)&0xff));
					i++;
					continue srcloop;
				case 'u':
				case 'U':
					// unicode hex escape
					if(srcLen - i < 5)
						if(ignoreError)
							return dst;
						else
							throw new EscapeException("String to escape ends in truncated unicode hex escape");
					i++;
					//System.err.println("unescaped=" + src.subSequence(i,i+4));
					//System.err.println("unhexShort=" + Integer.toHexString(unhexShort(src,i,4)) + '=');
					dst.append((char)(Hex.unhexShort(src,i,4)&0xffff));
					i+=3;
					continue srcloop;
				default:
					dst.append(ch);
					continue srcloop;
			}
		}
		return dst;
	}

	public static Appendable unescape(CharSequence src, Appendable dst, char escapeChar) throws IOException, EscapeException
	{
		return unescape(src,dst,escapeChar,DEFAULT_IGNORE_ERROR);
	}

	public static Appendable unescape(CharSequence src, Appendable dst, boolean ignoreError) throws IOException, EscapeException
	{
		return unescape(src,dst, DEFAULT_ESCAPE, ignoreError);
	}

	public static Appendable unescape(CharSequence src, Appendable dst) throws IOException, EscapeException
	{
		return unescape(src,dst, DEFAULT_ESCAPE, DEFAULT_IGNORE_ERROR);
	}

	public static String unescape(CharSequence src, char escapeChar,  boolean ignoreError) throws EscapeException
	{
		try
		{
			return unescape(src, new StringBuilder(), escapeChar, ignoreError).toString();
		}
		catch(IOException e)
		{
			throw new IllegalStateException("IOException caught when appending to a " + StringBuilder.class.getName(), e);
		}
	}

	public static String unescape(CharSequence src, char escapeChar) throws EscapeException
	{
		return unescape(src, escapeChar, DEFAULT_IGNORE_ERROR);
	}

	public static String unescape(CharSequence src, boolean ignoreError) throws EscapeException
	{
		return unescape(src, DEFAULT_ESCAPE, ignoreError);
	}

	public static String unescape(CharSequence src) throws EscapeException
	{
		return unescape(src, DEFAULT_ESCAPE, DEFAULT_IGNORE_ERROR);
	}

	public static Appendable escape(CharSequence src, Appendable dst, char[] alsoEscape, char escapeChar) throws IOException
	{
		int srcLen = src.length();
		char ch;	// char from src we're looking at
		int c;		// postive int form of ch
		int i;		// src position
		int j;		// alsoEscape position

		srcloop: for(i=0;i0xff)
			{
				dst.append(escapeChar);
				dst.append("u");
				Hex.hexShort(dst, c);
				continue srcloop;
			}
			if(c>=0x7f||c<0x20)
			{
				dst.append(escapeChar);
				dst.append('x');
				Hex.hexByte(dst,c);
				continue srcloop;
			}
			if(ch==escapeChar)
			{
				dst.append(escapeChar);
				dst.append(escapeChar);
				continue srcloop;
			}
			for(j=0;j parts = new ArrayList(len/2);
		for(int end=off+len;off 0)
			part = src.subSequence(start, off).toString();
		else
			part = "";
		parts.add(part);
		return parts.toArray(EMPTY_STRING_ARRAY);
	}

	public static String[] splitUnescaped(CharSequence src, int off, int len, char delim)
	{
		return splitUnescaped(src, off, len, delim, DEFAULT_ESCAPE);
	}

	public static String[] splitUnescaped(CharSequence src, int off, char delim)
	{
		return splitUnescaped(src, off, src.length()-off, delim, DEFAULT_ESCAPE);
	}

	public static String[] splitUnescaped(CharSequence src, char delim)
	{
		return splitUnescaped(src, 0, src.length(), delim, DEFAULT_ESCAPE);
	}

	public static Appendable joinEscaped(Appendable dst, char delim, char escapeChar, String... strs) throws IOException
	{
		char[] alsoEscape;
		int i;

		if(strs == null || strs.length==0)
			return dst;
		alsoEscape = new char[1];
		alsoEscape[0] = delim;
		for(i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy