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

org.dmfs.rfc3986.encoding.Enc Maven / Gradle / Ivy

There is a newer version: 0.8.1
Show newest version
/*
 * Copyright 2017 dmfs GmbH
 *
 * 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.
 */

package org.dmfs.rfc3986.encoding;

import org.dmfs.rfc3986.UriEncoded;
import org.dmfs.rfc3986.encoding.utils.PercentEncodingOutputStream;
import org.dmfs.rfc3986.validation.BitMapCharSet;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;


/**
 * A lazily encoded {@link CharSequence}. This encodes all reserved characters and delimiters. The only characters not encoded are "a"-"z",
 * "A"-"Z", "0"-"9", "-", "_", "." and "~".
 *
 * @author Marten Gajda
 * @see RFC 3986 Section 2.3
 */
public final class Enc implements UriEncoded
{
    private final CharSequence mPlain;
    private final String mCharSet;
    private CharSequence mEncoded;


    public Enc(CharSequence plain)
    {
        this(plain, "UTF-8");
    }


    public Enc(CharSequence plain, String charSet)
    {
        mPlain = plain;
        mCharSet = charSet;
    }


    @Override
    public UriEncoded normalized()
    {
        // this will be encoded in a normalized form
        return this;
    }


    @Override
    public CharSequence plain(String charset)
    {
        return mPlain;
    }


    @Override
    public CharSequence plain()
    {
        return mPlain;
    }


    @Override
    public int length()
    {
        return toString().length();
    }


    @Override
    public char charAt(int i)
    {
        return toString().charAt(i);
    }


    @Override
    public CharSequence subSequence(int i, int i1)
    {
        return toString().subSequence(i, i1);
    }


    @Override
    public int hashCode()
    {
        return toString().hashCode();
    }


    @Override
    public boolean equals(Object obj)
    {
        return obj instanceof UriEncoded && toString().equals(((UriEncoded) obj).normalized().toString());
    }


    @Override
    public String toString()
    {
        if (mEncoded == null)
        {
            try
            {
                mEncoded = encoded(mPlain, mCharSet);
            }
            catch (UnsupportedEncodingException e)
            {
                throw new IllegalArgumentException(String.format("Charset %s not supported by Runtime", mCharSet));
            }
        }
        return mEncoded.toString();
    }


    private CharSequence encoded(CharSequence charSequence, String charSet) throws UnsupportedEncodingException
    {
        final int len = charSequence.length();
        if (len == 0)
        {
            return Special.EMPTY;
        }
        try
        {
            // TODO: improve the performance. This appears to have quite some overhead compared to URLEncoder.encode().
            PercentEncodingOutputStream out = new PercentEncodingOutputStream(len, BitMapCharSet.UNRESERVED);
            Writer w = new OutputStreamWriter(out, charSet);
            w.append(charSequence);
            w.close();
            return out.toString();
        }
        catch (UnsupportedEncodingException e)
        {
            throw e;
        }
        catch (IOException e)
        {
            throw new RuntimeException("IOException while operating on CharSequences");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy