KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > env > StringBuilderValue


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.env;
31
32 import com.caucho.quercus.Quercus;
33
34 import java.io.IOException JavaDoc;
35 import java.io.ObjectInputStream JavaDoc;
36 import java.io.ObjectOutputStream JavaDoc;
37 import java.io.PrintWriter JavaDoc;
38 import java.io.Serializable JavaDoc;
39
40 /**
41  * Represents a PHP string value.
42  */

43 public class StringBuilderValue extends UnicodeValue
44   implements Serializable JavaDoc
45 {
46   private char []_buffer;
47   private int _length;
48
49   private String JavaDoc _value;
50
51   public StringBuilderValue()
52   {
53     _buffer = new char[128];
54   }
55
56   public StringBuilderValue(int capacity)
57   {
58     if (capacity < 64)
59       capacity = 64;
60
61     _buffer = new char[capacity];
62   }
63
64   public StringBuilderValue(String JavaDoc value)
65   {
66     if (value == null)
67       value = "";
68     
69     int length = value.length();
70     
71     _buffer = new char[length];
72
73     _length = length;
74
75     value.getChars(0, length, _buffer, 0);
76
77     _value = value;
78   }
79
80   public StringBuilderValue(String JavaDoc value, int minLength)
81   {
82     if (value == null)
83       value = "";
84     
85     _length = value.length();
86     _value = value;
87     
88     int length = _length;
89
90     if (length < minLength)
91       length = minLength;
92     
93     _buffer = new char[length];
94
95     value.getChars(0, _length, _buffer, 0);
96   }
97
98   public StringBuilderValue(char []buffer, int offset, int length)
99   {
100     int capacity;
101
102     if (length < 64)
103       capacity = 128;
104     else
105       capacity = 2 * length;
106
107     _buffer = new char[capacity];
108     _length = length;
109
110     System.arraycopy(buffer, offset, _buffer, 0, length);
111   }
112
113   public StringBuilderValue(char []buffer)
114   {
115     this(buffer, 0, buffer.length);
116   }
117
118   public StringBuilderValue(char []buffer, int offset, int length,
119                             boolean isExact)
120   {
121     _buffer = new char[length];
122     _length = length;
123
124     System.arraycopy(buffer, offset, _buffer, 0, length);
125   }
126
127   public StringBuilderValue(Character JavaDoc []buffer)
128   {
129     int length = buffer.length;
130     
131     _buffer = new char[length];
132     _length = length;
133     
134     for (int i = 0; i < length; i++) {
135       _buffer[i] = buffer[i].charValue();
136     }
137   }
138   
139   /**
140    * Returns the value.
141    */

142   public String JavaDoc getValue()
143   {
144     return toString();
145   }
146
147   /**
148    * Returns the type.
149    */

150   public String JavaDoc getType()
151   {
152     return "string";
153   }
154
155   /**
156    * Interns the string.
157    */

158   public InternStringValue intern(Quercus quercus)
159   {
160     return quercus.intern(toString());
161   }
162
163   /**
164    * Returns true for a long
165    */

166   public boolean isLongConvertible()
167   {
168     char []buffer = _buffer;
169     int len = _length;
170
171     if (len == 0)
172       return true;
173
174     int i = 0;
175     char ch = _buffer[0];
176
177     if (ch == '-' || ch == '+')
178       i++;
179
180     for (; i < len; i++) {
181       ch = _buffer[i];
182
183       if (! ('0' <= ch && ch <= '9'))
184         return false;
185     }
186
187     return true;
188   }
189
190   /**
191    * Returns true for a double
192    */

193   public boolean isDouble()
194   {
195     return getNumericType() == IS_DOUBLE;
196   }
197
198   /**
199    * Returns true for a number
200    */

201   @Override JavaDoc
202   public boolean isNumber()
203   {
204     return getNumericType() != IS_STRING;
205   }
206
207   /**
208    * Returns true for a scalar
209    */

210   public boolean isScalar()
211   {
212     return true;
213   }
214
215   /**
216    * Converts to a double.
217    */

218   protected int getNumericType()
219   {
220     char []buffer = _buffer;
221     int len = _length;
222
223     if (len == 0) {
224       // php/120y
225
return IS_STRING;
226     }
227
228     int i = 0;
229     int ch = 0;
230     boolean hasPoint = false;
231
232     if (i < len && ((ch = buffer[i]) == '+' || ch == '-')) {
233       i++;
234     }
235
236     if (len <= i)
237       return IS_STRING;
238
239     ch = buffer[i];
240
241     if (ch == '.') {
242       for (i++; i < len && '0' <= (ch = buffer[i]) && ch <= '9'; i++) {
243         return IS_DOUBLE;
244       }
245
246       return IS_STRING;
247     }
248     else if (! ('0' <= ch && ch <= '9'))
249       return IS_STRING;
250
251     for (; i < len && '0' <= (ch = buffer[i]) && ch <= '9'; i++) {
252     }
253
254     if (len <= i)
255       return IS_LONG;
256     else if (ch == '.' || ch == 'e' || ch == 'E') {
257       for (i++;
258            i < len && ('0' <= (ch = buffer[i]) && ch <= '9' ||
259                        ch == '+' || ch == '-' || ch == 'e' || ch == 'E');
260            i++) {
261       }
262
263       if (i < len)
264         return IS_STRING;
265       else
266         return IS_DOUBLE;
267     }
268     else
269       return IS_STRING;
270   }
271
272   /**
273    * Converts to a boolean.
274    */

275   public boolean toBoolean()
276   {
277     if (_length == 0)
278       return false;
279     else if (_length == 1 && _buffer[0] == '0')
280       return false;
281     else
282       return true;
283   }
284
285   /**
286    * Converts to a long.
287    */

288   public long toLong()
289   {
290     return toLong(_buffer, 0, _length);
291   }
292
293   /**
294    * Converts to a long.
295    */

296   public static long toLong(char []buffer, int offset, int len)
297   {
298     if (len == 0)
299       return 0;
300
301     long value = 0;
302     long sign = 1;
303
304     int i = 0;
305     int end = offset + len;
306
307     char ch = buffer[offset];
308     if (ch == '-') {
309       sign = -1;
310       offset++;
311     }
312     else if (ch == '+')
313       offset++;
314
315     while (offset < end) {
316       ch = buffer[offset++];
317
318       if ('0' <= ch && ch <= '9')
319         value = 10 * value + ch - '0';
320       else
321         return sign * value;
322     }
323
324     return sign * value;
325   }
326
327   /**
328    * Converts to a double.
329    */

330   public double toDouble()
331   {
332     char []buffer = _buffer;
333     int len = _length;
334     int i = 0;
335     int ch = 0;
336
337     if (i < len && ((ch = buffer[i]) == '+' || ch == '-')) {
338       i++;
339     }
340
341     for (; i < len && '0' <= (ch = buffer[i]) && ch <= '9'; i++) {
342     }
343
344     if (ch == '.') {
345       for (i++; i < len && '0' <= (ch = buffer[i]) && ch <= '9'; i++) {
346       }
347
348       if (i == 1)
349     return 0;
350     }
351
352     if (ch == 'e' || ch == 'E') {
353       int e = i++;
354
355       if (i < len && (ch = buffer[i]) == '+' || ch == '-') {
356         i++;
357       }
358
359       for (; i < len && '0' <= (ch = buffer[i]) && ch <= '9'; i++) {
360       }
361
362       if (i == e + 1)
363         i = e;
364     }
365
366     if (i == 0)
367       return 0;
368
369     try {
370       if (i == len)
371     return Double.parseDouble(toString());
372       else
373     return Double.parseDouble(new String JavaDoc(_buffer, 0, i));
374     } catch (NumberFormatException JavaDoc e) {
375       return 0;
376     }
377   }
378
379   /**
380    * Converts to a string.
381    */

382   public String JavaDoc toString()
383   {
384     if (_value == null)
385       _value = new String JavaDoc(_buffer, 0, _length);
386
387     return _value;
388   }
389
390   /**
391    * Converts to an object.
392    */

393   public Object JavaDoc toJavaObject()
394   {
395     if (_value == null)
396       _value = new String JavaDoc(_buffer, 0, _length);
397
398     return _value;
399   }
400
401   /**
402    * Converts to a string builder
403    */

404   @Override JavaDoc
405   public StringValue toStringBuilder()
406   {
407     return new StringBuilderValue(_buffer, 0, _length);
408   }
409
410   /**
411    * Append to a string builder.
412    */

413   @Override JavaDoc
414   public void appendTo(StringBuilderValue sb)
415   {
416     sb.append(_buffer, 0, _length);
417   }
418
419   /**
420    * Converts to a key.
421    */

422   public Value toKey()
423   {
424     char []buffer = _buffer;
425     int len = _length;
426
427     if (len == 0)
428       return this;
429
430     int sign = 1;
431     long value = 0;
432
433     int i = 0;
434     char ch = buffer[i];
435     if (ch == '-') {
436       sign = -1;
437       i++;
438     }
439
440     for (; i < len; i++) {
441       ch = buffer[i];
442
443       if ('0' <= ch && ch <= '9')
444         value = 10 * value + ch - '0';
445       else
446         return this;
447     }
448
449     return new LongValue(sign * value);
450   }
451
452   /**
453    * Converts to a byte array, with no consideration of character encoding.
454    * Each character becomes one byte, characters with values above 255 are
455    * not correctly preserved.
456    */

457   public byte[] toBytes()
458   {
459     char []buffer = _buffer;
460
461     final int len = _length;
462     byte[] bytes = new byte[len];
463
464     for (int i = 0; i < len; i++) {
465       bytes[i] = (byte) buffer[i];
466     }
467
468     return bytes;
469   }
470
471   /**
472    * Returns the character at an index
473    */

474   public Value get(Value key)
475   {
476     return charValueAt(key.toLong());
477   }
478
479   /**
480    * Returns the character at an index
481    */

482   public Value getRef(Value key)
483   {
484     return charValueAt(key.toLong());
485   }
486
487   /**
488    * Returns the character at an index
489    */

490   @Override JavaDoc
491   public Value charValueAt(long index)
492   {
493     int len = _length;
494
495     if (index < 0 || len <= index)
496       return StringValue.EMPTY;
497     else
498       return StringValue.create(_buffer[(int) index]);
499   }
500
501   /**
502    * sets the character at an index
503    */

504   @Override JavaDoc
505   public Value setCharValueAt(long index, String JavaDoc value)
506   {
507     int len = _length;
508
509     if (index < 0 || len <= index)
510       return this;
511     else {
512       StringBuilderValue sb = new StringBuilderValue(_buffer, 0, (int) index);
513       sb.append(value);
514       sb.append(_buffer, (int) (index + 1), (int) (len - index - 1));
515
516       return sb;
517     }
518   }
519
520   //
521
// CharSequence
522
//
523

524   /**
525    * Returns the length of the string.
526    */

527   @Override JavaDoc
528   public int length()
529   {
530     return _length;
531   }
532
533   void setLength(int length)
534   {
535     _length = length;
536   }
537
538   /**
539    * Returns the character at a particular location
540    */

541   @Override JavaDoc
542   public final char charAt(int index)
543   {
544     return _buffer[index];
545   }
546
547   /**
548    * Returns a subsequence
549    */

550   @Override JavaDoc
551   public CharSequence JavaDoc subSequence(int start, int end)
552   {
553     if (end <= start)
554       return StringValue.EMPTY;
555     
556     char []newBuffer = new char[end - start];
557     
558     System.arraycopy(_buffer, start, newBuffer, 0, end - start);
559              
560     return new StringBuilderValue(newBuffer, 0, end - start);
561   }
562
563   //
564
// java.lang.String
565
//
566

567   /**
568    * Returns the last index of the match string, starting from the head.
569    */

570   @Override JavaDoc
571   public int indexOf(char match)
572   {
573     int length = _length;
574     char []buffer = _buffer;
575     
576     for (int head = 0; head < length; head++) {
577       if (buffer[head] == match)
578     return head;
579     }
580
581     return -1;
582   }
583     
584   /**
585    * Returns the last index of the match string, starting from the head.
586    */

587   @Override JavaDoc
588   public int indexOf(char match, int head)
589   {
590     int length = _length;
591     char []buffer = _buffer;
592     
593     for (; head < length; head++) {
594       if (buffer[head] == match)
595     return head;
596     }
597
598     return -1;
599   }
600     
601   /**
602    * Returns the first index of the match string, starting from the head.
603    */

604   @Override JavaDoc
605   public int indexOf(CharSequence JavaDoc match, int head)
606   {
607     int length = _length;
608     int matchLength = match.length();
609
610     if (matchLength <= 0)
611       return -1;
612     else if (head < 0)
613       return -1;
614     
615     int end = length - matchLength;
616     char first = match.charAt(0);
617
618     char []buffer = _buffer;
619     
620     loop:
621     for (; head <= end; head++) {
622       if (buffer[head] != first)
623     continue;
624
625       for (int i = 1; i < matchLength; i++) {
626     if (buffer[head + i] != match.charAt(i))
627       continue loop;
628       }
629
630       return head;
631     }
632
633     return -1;
634   }
635
636   /**
637    * Returns a character array
638    */

639   @Override JavaDoc
640   public char []toCharArray()
641   {
642     char[] dest = new char[_length];
643     
644     System.arraycopy(_buffer, 0, dest, 0, _length);
645     
646     return dest;
647   }
648   
649   /**
650    * Returns the buffer backing this StringBuilderValue.
651    */

652   public char []getBuffer()
653   {
654     return _buffer;
655   }
656
657   /**
658    * Prints the value.
659    * @param env
660    */

661   public void print(Env env)
662   {
663     env.print(_buffer, 0, _length);
664   }
665
666   /**
667    * Serializes the value.
668    */

669   public void serialize(StringBuilder JavaDoc sb)
670   {
671     sb.append("s:");
672     sb.append(_length);
673     sb.append(":\"");
674     sb.append(_buffer, 0, _length);
675     sb.append("\";");
676   }
677
678   //
679
// append code
680
//
681

682   /**
683    * Append a Java string to the value.
684    */

685   @Override JavaDoc
686   public final StringValue append(String JavaDoc s)
687   {
688     int len = s.length();
689
690     if (_buffer.length < _length + len)
691       ensureCapacity(_length + len);
692
693     s.getChars(0, len, _buffer, _length);
694
695     _length += len;
696     _value = null;
697
698     return this;
699   }
700
701   /**
702    * Append a Java string to the value.
703    */

704   @Override JavaDoc
705   public final StringValue append(String JavaDoc s, int start, int end)
706   {
707     int len = end - start;
708
709     if (_buffer.length < _length + len)
710       ensureCapacity(_length + len);
711
712     s.getChars(start, end, _buffer, _length);
713
714     _length += len;
715     _value = null;
716
717     return this;
718   }
719
720   /**
721    * Append a Java buffer to the value.
722    */

723   @Override JavaDoc
724   public final StringValue append(char []buf, int offset, int length)
725   {
726     if (_buffer.length < _length + length)
727       ensureCapacity(_length + length);
728
729     System.arraycopy(buf, offset, _buffer, _length, length);
730
731     _length += length;
732     _value = null;
733
734     return this;
735   }
736
737   /**
738    * Append a Java buffer to the value.
739    */

740   @Override JavaDoc
741   public final StringValue append(CharSequence JavaDoc buf, int head, int tail)
742   {
743     _value = null;
744     
745     int length = tail - head;
746     
747     if (_buffer.length < _length + length)
748       ensureCapacity(_length + length);
749
750     if (buf instanceof StringBuilderValue) {
751       StringBuilderValue sb = (StringBuilderValue) buf;
752       
753       System.arraycopy(sb._buffer, head, _buffer, _length, tail - head);
754
755       _length += tail - head;
756     } else {
757       for (; head < tail; head++)
758     _buffer[_length++] = buf.charAt(head);
759     }
760
761     return this;
762   }
763
764   /**
765    * Append a Java buffer to the value.
766    */

767   @Override JavaDoc
768   public final StringValue append(StringBuilderValue sb, int head, int tail)
769   {
770     _value = null;
771     
772     int length = tail - head;
773     
774     if (_buffer.length < _length + length)
775       ensureCapacity(_length + length);
776
777     System.arraycopy(sb._buffer, head, _buffer, _length, tail - head);
778
779     _length += tail - head;
780
781     return this;
782   }
783
784   /**
785    * Append a Java char to the value.
786    */

787   @Override JavaDoc
788   public final StringValue append(char v)
789   {
790     _value = null;
791     
792     if (_buffer.length < _length + 1)
793       ensureCapacity(_length + 1);
794
795     _buffer[_length++] = v;
796
797     return this;
798   }
799
800   /**
801    * Append a Java value to the value.
802    */

803   @Override JavaDoc
804   public final StringValue append(Value v)
805   {
806     _value = null;
807     
808     v.appendTo(this);
809
810     return this;
811   }
812
813   //
814
// java.lang.Object methods
815
//
816

817   /**
818    * Returns the hash code.
819    */

820   public int hashCode()
821   {
822     int hash = 37;
823
824     int length = _length;
825     char []buffer = _buffer;
826
827     for (int i = 0; i < length; i++) {
828       hash = 65521 * hash + buffer[i];
829     }
830
831     return hash;
832   }
833
834   /**
835    * Test for equality
836    */

837   public boolean equals(Object JavaDoc o)
838   {
839     if (this == o)
840       return true;
841     else if (o instanceof StringBuilderValue) {
842       StringBuilderValue s = (StringBuilderValue) o;
843
844       int aLength = _length;
845       int bLength = s._length;
846
847       if (aLength != bLength)
848     return false;
849
850       char []aBuffer = _buffer;
851       char []bBuffer = s._buffer;
852
853       for (int i = aLength - 1; i >= 0; i--) {
854     if (aBuffer[i] != bBuffer[i])
855       return false;
856       }
857
858       return true;
859     }
860     else if (o instanceof StringValue) {
861       StringValue s = (StringValue) o;
862
863       int aLength = length();
864       int bLength = s.length();
865
866       if (aLength != bLength)
867     return false;
868
869       for (int i = aLength - 1; i >= 0; i--) {
870     if (charAt(i) != s.charAt(i))
871       return false;
872       }
873
874       return true;
875     } else {
876       return false;
877     }
878   }
879
880   //
881
// Java generator code
882
//
883

884   /**
885    * Generates code to recreate the expression.
886    *
887    * @param out the writer to the Java source code.
888    */

889   public void generate(PrintWriter JavaDoc out)
890     throws IOException JavaDoc
891   {
892     out.print("new InternStringValue(\"");
893     printJavaString(out, toString());
894     out.print("\")");
895   }
896
897   private void ensureCapacity(int capacity)
898   {
899     if (capacity <= _buffer.length)
900       return;
901
902     int newCapacity;
903
904     if (capacity < 4096) {
905       newCapacity = _buffer.length;
906
907       if (newCapacity < 64)
908     newCapacity = 64;
909
910       while (newCapacity < capacity)
911     newCapacity = 4 * newCapacity;
912     }
913     else
914       newCapacity = (capacity + 4096) & ~4095;
915
916     char []buffer = new char[newCapacity];
917     System.arraycopy(_buffer, 0, buffer, 0, _length);
918
919     _buffer = buffer;
920   }
921   
922   //
923
// Java serialization code
924
//
925

926   private void writeObject(ObjectOutputStream JavaDoc out)
927     throws IOException JavaDoc
928   {
929     out.writeInt(_length);
930     
931     for (int i = 0; i < _length; i++) {
932       out.writeChar(_buffer[i]);
933     }
934   }
935   
936   private void readObject(ObjectInputStream JavaDoc in)
937     throws ClassNotFoundException JavaDoc, IOException JavaDoc
938   {
939     _length = in.readInt();
940     
941     _buffer = new char[_length];
942     
943     for (int i = 0; i < _length; i++) {
944       _buffer[i] = in.readChar();
945     }
946   }
947 }
948
949
Popular Tags