class TextLiteralExpression extends SimpleExpression {
    
    private static final Logger logger = LoggerFactory.getLogger(TextLiteralExpression.class);

    
    private static final long serialVersionUID = 6511847028638506552L;

    static final char ESCAPE_PREFIX = '\\';
    static final char DELIMITER = '\'';

    
    private final LiteralValue value;

    
    public TextLiteralExpression(final String value) {
        super();
        Validate.notNull(value, "Value cannot be null");
        this.value = new LiteralValue(unwrapLiteral(value));
    }
    
    
    
    public LiteralValue getValue() {
        return this.value;
    }


    private static String unwrapLiteral(final String input) {
        // We know input is not null
        final int inputLen = input.length();
        if (inputLen > 1 && input.charAt(0) == '\'' && input.charAt(inputLen - 1) == '\'') {
            return unescapeLiteral(input.substring(1, inputLen - 1));
        }
        return input;
    }

    
    @Override
    public String getStringRepresentation() {
        return String.valueOf(DELIMITER) + 
               this.value.getValue().replace(String.valueOf(DELIMITER),("\\" + DELIMITER)) + 
               String.valueOf(DELIMITER);
    }


    
    static TextLiteralExpression parseTextLiteralExpression(final String input) {
        return new TextLiteralExpression(input);
        
    }
    

    
    static Object executeTextLiteralExpression(
            final IExpressionContext context,
            final TextLiteralExpression expression,
            final StandardExpressionExecutionContext expContext) {

        if (logger.isTraceEnabled()) {
            logger.trace("[THYMELEAF][{}] Evaluating text literal: \"{}\"", TemplateEngine.threadIndex(), expression.getStringRepresentation());
        }
        
        return expression.getValue();
        
    }



    public static String wrapStringIntoLiteral(final String str) {

        if (str == null) {
            return null;
        }

        int n = str.length();
        while (n-- != 0) {

            if (str.charAt(n) == '\'') {

                final StringBuilder strBuilder = new StringBuilder(str.length() + 5);

                strBuilder.append('\'');
                final int strLen = str.length();
                for (int i = 0; i < strLen; i++) {
                    final char c = str.charAt(i);
                    if (c == '\'') {
                        strBuilder.append('\\');
                    }
                    strBuilder.append(c);
                }
                strBuilder.append('\'');

                return strBuilder.toString();

            }

        }

        return '\'' + str + '\'';

    }



    static boolean isDelimiterEscaped(final String input, final int pos) {
        // Only an odd number of \'s will indicate escaping
        if (pos == 0 || input.charAt(pos - 1) != '\\') {
            return false;
        }
        int i = pos - 1;
        boolean odd = false;
        while (i >= 0) {
            if (input.charAt(i) == '\\') {
                odd = !odd;
            } else {
                return odd;
            }
            i--;
        }
        return odd;
    }




    /*
     * This unescape operation will perform two transformations:
     *   \' -> '
     *   \\ -> \
     */
    private static String unescapeLiteral(final String text) {<FILL_FUNCTION_BODY>}


}


        if (text == null) {
            return null;
        }

        StringBuilder strBuilder = null;

        final int max = text.length();

        int readOffset = 0;
        int referenceOffset = 0;

        char c;

        for (int i = 0; i < max; i++) {

            c = text.charAt(i);

            /*
             * Check the need for an unescape operation at this point
             */

            if (c != ESCAPE_PREFIX || (i + 1) >= max) {
                continue;
            }

            if (c == ESCAPE_PREFIX) {

                switch (text.charAt(i + 1)) {
                    case '\'': c = '\''; referenceOffset = i + 1; break;
                    case '\\': c = '\\'; referenceOffset = i + 1; break;
                    // We weren't able to consume any valid escape chars, just not consider it an escape operation
                    default: referenceOffset = i; break;
                }

            }


            /*
             * At this point we know for sure we will need some kind of unescape, so we
             * can increase the offset and initialize the string builder if needed, along with
             * copying to it all the contents pending up to this point.
             */

            if (strBuilder == null) {
                strBuilder = new StringBuilder(max + 5);
            }

            if (i - readOffset > 0) {
                strBuilder.append(text, readOffset, i);
            }

            i = referenceOffset;
            readOffset = i + 1;

            /*
             * Write the unescaped char
             */
            strBuilder.append(c);

        }


        /*
         * -----------------------------------------------------------------------------------------------
         * Final cleaning: return the original String object if no unescape was actually needed. Otherwise
         *                 append the remaining escaped text to the string builder and return.
         * -----------------------------------------------------------------------------------------------
         */

        if (strBuilder == null) {
            return text;
        }

        if (max - readOffset > 0) {
            strBuilder.append(text, readOffset, max);
        }

        return strBuilder.toString();

    
<methods><variables>static final char EXPRESSION_END_CHAR,static final char EXPRESSION_START_CHAR,private static final long serialVersionUID