001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.util.string; 018 019/** 020 * This is a prepending stringbuffer optimized for constantly prepending strings to the front of the 021 * buffer. 022 * 023 * @author jcompagner 024 */ 025public class PrependingStringBuffer 026{ 027 private int size; 028 private int position; 029 030 private char[] buffer; 031 032 /** 033 * Default constructor, the internal initial buffer size will be 16 034 */ 035 public PrependingStringBuffer() 036 { 037 this(16); 038 } 039 040 /** 041 * Constructs this PrependingStringBuffer with the given buffer size. 042 * 043 * @param size 044 * The initial size of the buffer. 045 */ 046 public PrependingStringBuffer(final int size) 047 { 048 buffer = new char[size]; 049 position = size; 050 this.size = 0; 051 } 052 053 /** 054 * Constructs and direct inserts the given string. The buffer size will be string.length+16 055 * 056 * @param start 057 * The string that is directly inserted. 058 */ 059 public PrependingStringBuffer(final String start) 060 { 061 this(start.length() + 16); 062 prepend(start); 063 } 064 065 /** 066 * Prepends one char to this PrependingStringBuffer 067 * 068 * @param ch 069 * The char that will be prepended 070 * @return this 071 */ 072 public PrependingStringBuffer prepend(final char ch) 073 { 074 int len = 1; 075 if (position < len) 076 { 077 expandCapacity(size + len); 078 } 079 position -= len; 080 buffer[position] = ch; 081 size += len; 082 return this; 083 } 084 085 /** 086 * Prepends the string to this PrependingStringBuffer 087 * 088 * @param str 089 * The string that will be prepended 090 * @return this 091 */ 092 public PrependingStringBuffer prepend(final String str) 093 { 094 int len = str.length(); 095 if (position < len) 096 { 097 expandCapacity(size + len); 098 } 099 str.getChars(0, len, buffer, position - len); 100 position -= len; 101 size += len; 102 return this; 103 } 104 105 private void expandCapacity(final int minimumCapacity) 106 { 107 int newCapacity = (buffer.length + 1) * 2; 108 if (newCapacity < 0) 109 { 110 newCapacity = Integer.MAX_VALUE; 111 } 112 else if (minimumCapacity > newCapacity) 113 { 114 newCapacity = minimumCapacity; 115 } 116 117 char newValue[] = new char[newCapacity]; 118 System.arraycopy(buffer, position, newValue, newCapacity - size, size); 119 buffer = newValue; 120 position = newCapacity - size; 121 } 122 123 /** 124 * Returns the size of this PrependingStringBuffer 125 * 126 * @return The size 127 */ 128 public int length() 129 { 130 return size; 131 } 132 133 /** 134 * @see java.lang.Object#toString() 135 */ 136 @Override 137 public String toString() 138 { 139 return new String(buffer, position, size); 140 } 141 142 @Override 143 public boolean equals(final Object obj) 144 { 145 if (obj == this) 146 { 147 return true; 148 } 149 else if (obj == null) 150 { 151 return false; 152 } 153 else 154 { 155 return toString().equals(obj.toString()); 156 } 157 } 158 159 @Override 160 public int hashCode() 161 { 162 return toString().hashCode(); 163 } 164}