Source Code Cross Referenced for StringValue.java in  » EJB-Server-resin-3.1.5 » quercus » com » caucho » quercus » env » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server resin 3.1.5 » quercus » com.caucho.quercus.env 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003:         *
0004:         * This file is part of Resin(R) Open Source
0005:         *
0006:         * Each copy or derived work must preserve the copyright notice and this
0007:         * notice unmodified.
0008:         *
0009:         * Resin Open Source is free software; you can redistribute it and/or modify
0010:         * it under the terms of the GNU General Public License as published by
0011:         * the Free Software Foundation; either version 2 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * Resin Open Source is distributed in the hope that it will be useful,
0015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017:         * of NON-INFRINGEMENT.  See the GNU General Public License for more
0018:         * details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with Resin Open Source; if not, write to the
0022:         *
0023:         *   Free Software Foundation, Inc.
0024:         *   59 Temple Place, Suite 330
0025:         *   Boston, MA 02111-1307  USA
0026:         *
0027:         * @author Scott Ferguson
0028:         */
0029:
0030:        package com.caucho.quercus.env;
0031:
0032:        import com.caucho.quercus.Quercus;
0033:        import com.caucho.quercus.QuercusModuleException;
0034:        import com.caucho.quercus.QuercusRuntimeException;
0035:        import com.caucho.quercus.lib.file.BinaryInput;
0036:        import com.caucho.vfs.TempBuffer;
0037:        import com.caucho.vfs.TempCharBuffer;
0038:        import com.caucho.vfs.TempStream;
0039:        import com.caucho.vfs.WriteStream;
0040:
0041:        import java.io.*;
0042:        import java.util.IdentityHashMap;
0043:
0044:        /**
0045:         * Represents a Quercus string value.
0046:         */
0047:        abstract public class StringValue extends Value implements  CharSequence {
0048:            public static final StringValue EMPTY = new StringBuilderValue("");
0049:
0050:            private final static StringValue[] CHAR_STRINGS;
0051:
0052:            protected static final int IS_STRING = 0;
0053:            protected static final int IS_LONG = 1;
0054:            protected static final int IS_DOUBLE = 2;
0055:
0056:            /**
0057:             * Creates the string.
0058:             */
0059:            public static Value create(String value) {
0060:                // XXX: needs updating for i18n, currently php5 only
0061:
0062:                if (value == null)
0063:                    return NullValue.NULL;
0064:                else
0065:                    return new StringBuilderValue(value);
0066:            }
0067:
0068:            /**
0069:             * Creates the string.
0070:             */
0071:            public static StringValue create(char value) {
0072:                // XXX: needs updating for i18n, currently php5 only
0073:
0074:                if (value < CHAR_STRINGS.length)
0075:                    return CHAR_STRINGS[value];
0076:                else
0077:                    return new StringBuilderValue(String.valueOf(value));
0078:            }
0079:
0080:            /**
0081:             * Creates the string.
0082:             */
0083:            public static Value create(Object value) {
0084:                // XXX: needs updating for i18n, currently php5 only
0085:
0086:                if (value == null)
0087:                    return NullValue.NULL;
0088:                else
0089:                    return new StringBuilderValue(value.toString());
0090:            }
0091:
0092:            /*
0093:             * Decodes the Unicode str from charset.
0094:             * 
0095:             * @param str should be a Unicode string
0096:             * @param charset to decode string from
0097:             */
0098:            public StringValue create(Env env, StringValue unicodeStr,
0099:                    String charset) {
0100:                if (!unicodeStr.isUnicode())
0101:                    return unicodeStr;
0102:
0103:                try {
0104:                    StringValue sb = createStringBuilder();
0105:
0106:                    byte[] bytes = unicodeStr.toString().getBytes(charset);
0107:
0108:                    sb.append(bytes);
0109:                    return sb;
0110:
0111:                } catch (UnsupportedEncodingException e) {
0112:                    env.warning(e);
0113:
0114:                    return unicodeStr;
0115:                }
0116:            }
0117:
0118:            /**
0119:             * Creates a string builder of the same type.
0120:             */
0121:            abstract public StringValue createStringBuilder();
0122:
0123:            /**
0124:             * Creates a string builder of the same type.
0125:             */
0126:            abstract public StringValue createStringBuilder(int length);
0127:
0128:            /*
0129:             * Returns the immutable empty string of same type.
0130:             */
0131:            abstract public StringValue getEmptyString();
0132:
0133:            //
0134:            // Predicates and relations
0135:            //
0136:
0137:            /**
0138:             * Returns the type.
0139:             */
0140:            public String getType() {
0141:                return "string";
0142:            }
0143:
0144:            /**
0145:             * Returns the ValueType.
0146:             */
0147:            @Override
0148:            public ValueType getValueType() {
0149:                return ValueType.STRING;
0150:            }
0151:
0152:            /**
0153:             * Returns true for a long
0154:             */
0155:            public boolean isLongConvertible() {
0156:                return getValueType().isLongCmp();
0157:            }
0158:
0159:            /**
0160:             * Returns true for a double
0161:             */
0162:            public boolean isDoubleConvertible() {
0163:                return getValueType().isNumberCmp();
0164:            }
0165:
0166:            /**
0167:             * Returns true for a number
0168:             */
0169:            public boolean isNumber() {
0170:                return false;
0171:            }
0172:
0173:            /**
0174:             * Returns true for is_numeric
0175:             */
0176:            @Override
0177:            public boolean isNumeric() {
0178:                // php/120y
0179:
0180:                return getValueType().isNumberCmp();
0181:            }
0182:
0183:            /**
0184:             * Returns true for a scalar
0185:             */
0186:            public boolean isScalar() {
0187:                return true;
0188:            }
0189:
0190:            /**
0191:             * Returns true for StringValue
0192:             */
0193:            @Override
0194:            public boolean isString() {
0195:                return true;
0196:            }
0197:
0198:            /*
0199:             * Returns true if this is a PHP5 string.
0200:             */
0201:            public boolean isPHP5String() {
0202:                return false;
0203:            }
0204:
0205:            /**
0206:             * Returns true if the value is empty
0207:             */
0208:            @Override
0209:            public boolean isEmpty() {
0210:                return length() == 0 || length() == 1 && charAt(0) == '0';
0211:            }
0212:
0213:            /**
0214:             * Returns true for equality
0215:             */
0216:            public int cmp(Value rValue) {
0217:                if (isNumberConvertible() || rValue.isNumberConvertible()) {
0218:                    double l = toDouble();
0219:                    double r = rValue.toDouble();
0220:
0221:                    if (l == r)
0222:                        return 0;
0223:                    else if (l < r)
0224:                        return -1;
0225:                    else
0226:                        return 1;
0227:                } else {
0228:                    int result = toString().compareTo(rValue.toString());
0229:
0230:                    if (result == 0)
0231:                        return 0;
0232:                    else if (result > 0)
0233:                        return 1;
0234:                    else
0235:                        return -1;
0236:                }
0237:            }
0238:
0239:            /**
0240:             * Returns true for equality
0241:             */
0242:            @Override
0243:            public boolean eq(Value rValue) {
0244:                ValueType typeA = getValueType();
0245:                ValueType typeB = rValue.getValueType();
0246:
0247:                if (typeB.isNumber()) {
0248:                    double l = toDouble();
0249:                    double r = rValue.toDouble();
0250:
0251:                    return l == r;
0252:                } else if (typeB.isBoolean()) {
0253:                    return toBoolean() == rValue.toBoolean();
0254:                } else if (typeA.isNumberCmp() && typeB.isNumberCmp()) {
0255:                    double l = toDouble();
0256:                    double r = rValue.toDouble();
0257:
0258:                    return l == r;
0259:                } else {
0260:                    return toString().equals(rValue.toString());
0261:                }
0262:            }
0263:
0264:            /**
0265:             * Compare two strings
0266:             */
0267:            public int cmpString(StringValue rValue) {
0268:                return toString().compareTo(rValue.toString());
0269:            }
0270:
0271:            // Conversions
0272:
0273:            /**
0274:             * Converts to a string value.
0275:             */
0276:            public StringValue toStringValue() {
0277:                return this ;
0278:            }
0279:
0280:            /**
0281:             * Converts to a long.
0282:             */
0283:            public static long toLong(String string) {
0284:                if (string.equals(""))
0285:                    return 0;
0286:
0287:                int len = string.length();
0288:
0289:                long value = 0;
0290:                long sign = 1;
0291:
0292:                int i = 0;
0293:                char ch = string.charAt(0);
0294:
0295:                if (ch == '-') {
0296:                    sign = -1;
0297:                    i = 1;
0298:                } else if (ch == '+')
0299:                    i = 1;
0300:
0301:                for (; i < len; i++) {
0302:                    ch = string.charAt(i);
0303:
0304:                    if ('0' <= ch && ch <= '9')
0305:                        value = 10 * value + ch - '0';
0306:                    else
0307:                        return sign * value;
0308:                }
0309:
0310:                return value;
0311:            }
0312:
0313:            /**
0314:             * Converts to a double.
0315:             */
0316:            public double toDouble() {
0317:                return toDouble(toString());
0318:            }
0319:
0320:            /**
0321:             * Converts to a double.
0322:             */
0323:            public static double toDouble(String s) {
0324:                int len = s.length();
0325:                int i = 0;
0326:                int ch = 0;
0327:
0328:                if (i < len && ((ch = s.charAt(i)) == '+' || ch == '-')) {
0329:                    i++;
0330:                }
0331:
0332:                for (; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) {
0333:                }
0334:
0335:                if (ch == '.') {
0336:                    for (i++; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) {
0337:                    }
0338:                }
0339:
0340:                if (ch == 'e' || ch == 'E') {
0341:                    int e = i++;
0342:
0343:                    if (i < len && (ch = s.charAt(i)) == '+' || ch == '-') {
0344:                        i++;
0345:                    }
0346:
0347:                    for (; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) {
0348:                    }
0349:
0350:                    if (i == e + 1)
0351:                        i = e;
0352:                }
0353:
0354:                if (i == 0)
0355:                    return 0;
0356:                else if (i == len)
0357:                    return Double.parseDouble(s);
0358:                else
0359:                    return Double.parseDouble(s.substring(0, i));
0360:            }
0361:
0362:            /**
0363:             * Converts to a boolean.
0364:             */
0365:            public boolean toBoolean() {
0366:                int length = length();
0367:
0368:                if (length == 0)
0369:                    return false;
0370:                else if (length > 1)
0371:                    return true;
0372:                else
0373:                    return charAt(0) != '0';
0374:            }
0375:
0376:            /**
0377:             * Converts to a key.
0378:             */
0379:            public Value toKey() {
0380:                int len = length();
0381:
0382:                if (len == 0)
0383:                    return this ;
0384:
0385:                int sign = 1;
0386:                long value = 0;
0387:
0388:                int i = 0;
0389:                char ch = charAt(i);
0390:                if (ch == '-') {
0391:                    sign = -1;
0392:                    i++;
0393:                }
0394:
0395:                for (; i < len; i++) {
0396:                    ch = charAt(i);
0397:
0398:                    if ('0' <= ch && ch <= '9')
0399:                        value = 10 * value + ch - '0';
0400:                    else
0401:                        return this ;
0402:                }
0403:
0404:                return LongValue.create(sign * value);
0405:            }
0406:
0407:            /**
0408:             * Converts to an object.
0409:             */
0410:            @Override
0411:            final public Value toAutoObject(Env env) {
0412:                return env.createObject();
0413:            }
0414:
0415:            /**
0416:             * Converts to a Java object.
0417:             */
0418:            public Object toJavaObject() {
0419:                return toString();
0420:            }
0421:
0422:            /**
0423:             * Takes the values of this array, unmarshalls them to objects of type
0424:             * <i>elementType</i>, and puts them in a java array.
0425:             */
0426:            @Override
0427:            public Object valuesToArray(Env env, Class elementType) {
0428:                if (char.class.equals(elementType)) {
0429:                    return toUnicodeValue(env).toCharArray();
0430:                } else if (Character.class.equals(elementType)) {
0431:                    char[] chars = toUnicodeValue(env).toCharArray();
0432:
0433:                    int length = chars.length;
0434:
0435:                    Character[] charObjects = new Character[length];
0436:
0437:                    for (int i = 0; i < length; i++) {
0438:                        charObjects[i] = Character.valueOf(chars[i]);
0439:                    }
0440:
0441:                    return charObjects;
0442:                } else if (byte.class.equals(elementType)) {
0443:                    return toBinaryValue(env).toBytes();
0444:                } else if (Byte.class.equals(elementType)) {
0445:                    byte[] bytes = toBinaryValue(env).toBytes();
0446:
0447:                    int length = bytes.length;
0448:
0449:                    Byte[] byteObjects = new Byte[length];
0450:
0451:                    for (int i = 0; i < length; i++) {
0452:                        byteObjects[i] = Byte.valueOf(bytes[i]);
0453:                    }
0454:
0455:                    return byteObjects;
0456:                } else {
0457:                    env.error(L.l("Can't assign {0} with type {1} to {2}",
0458:                            this , this .getClass(), elementType));
0459:                    return null;
0460:                }
0461:            }
0462:
0463:            /**
0464:             * Converts to an array if null.
0465:             */
0466:            public Value toAutoArray() {
0467:                if (length() == 0)
0468:                    return new ArrayValueImpl();
0469:                else
0470:                    return this ;
0471:            }
0472:
0473:            // Operations
0474:
0475:            /**
0476:             * Returns the character at an index
0477:             */
0478:            public Value get(Value key) {
0479:                return charValueAt(key.toLong());
0480:            }
0481:
0482:            /**
0483:             * Returns the character at an index
0484:             */
0485:            public Value getArg(Value key) {
0486:                // php/03ma
0487:                return charValueAt(key.toLong());
0488:            }
0489:
0490:            /**
0491:             * Returns the character at an index
0492:             */
0493:            public Value getRef(Value key) {
0494:                return charValueAt(key.toLong());
0495:            }
0496:
0497:            /**
0498:             * Returns the character at an index
0499:             */
0500:            @Override
0501:            public Value charValueAt(long index) {
0502:                int len = length();
0503:
0504:                if (index < 0 || len <= index)
0505:                    return UnsetUnicodeValue.UNSET;
0506:                else {
0507:                    return StringValue.create(charAt((int) index));
0508:                }
0509:            }
0510:
0511:            /**
0512:             * sets the character at an index
0513:             */
0514:            @Override
0515:            public Value setCharValueAt(long index, String value) {
0516:                int len = length();
0517:
0518:                if (index < 0 || len <= index)
0519:                    return this ;
0520:                else {
0521:                    return (createStringBuilder().append(this , 0, (int) index)
0522:                            .append(value).append(this , (int) (index + 1),
0523:                            length()));
0524:                }
0525:            }
0526:
0527:            /**
0528:             * Pre-increment the following value.
0529:             */
0530:            public Value preincr(int incr) {
0531:                return postincr(incr);
0532:            }
0533:
0534:            /**
0535:             * Post-increment the following value.
0536:             */
0537:            public Value postincr(int incr) {
0538:                // php/03i6
0539:                if (length() == 0) {
0540:                    if (incr == 1)
0541:                        return createStringBuilder().append("1");
0542:                    else
0543:                        return LongValue.MINUS_ONE;
0544:                }
0545:
0546:                if (incr > 0) {
0547:                    StringBuilder tail = new StringBuilder();
0548:
0549:                    for (int i = length() - 1; i >= 0; i--) {
0550:                        char ch = charAt(i);
0551:
0552:                        if (ch == 'z') {
0553:                            if (i == 0)
0554:                                return createStringBuilder().append("aa")
0555:                                        .append(tail);
0556:                            else
0557:                                tail.insert(0, 'a');
0558:                        } else if ('a' <= ch && ch < 'z') {
0559:                            return (createStringBuilder().append(this , 0, i)
0560:                                    .append((char) (ch + 1)).append(tail));
0561:                        } else if (ch == 'Z') {
0562:                            if (i == 0)
0563:                                return createStringBuilder().append("AA")
0564:                                        .append(tail);
0565:                            else
0566:                                tail.insert(0, 'A');
0567:                        } else if ('A' <= ch && ch < 'Z') {
0568:                            return (createStringBuilder().append(this , 0, i)
0569:                                    .append((char) (ch + 1)).append(tail));
0570:                        } else if ('0' <= ch && ch <= '9' && i == length() - 1) {
0571:                            return LongValue.create(toLong() + incr);
0572:                        }
0573:                    }
0574:
0575:                    return createStringBuilder().append(tail.toString());
0576:                } else if (getValueType().isLongAdd()) {
0577:                    return LongValue.create(toLong() + incr);
0578:                } else {
0579:                    return this ;
0580:                }
0581:            }
0582:
0583:            /**
0584:             * Adds to the following value.
0585:             */
0586:            public Value add(long rValue) {
0587:                if (getValueType().isLongAdd())
0588:                    return LongValue.create(toLong() + rValue);
0589:
0590:                return DoubleValue.create(toDouble() + rValue);
0591:            }
0592:
0593:            /**
0594:             * Adds to the following value.
0595:             */
0596:            public Value sub(long rValue) {
0597:                if (getValueType().isLongAdd())
0598:                    return LongValue.create(toLong() - rValue);
0599:
0600:                return DoubleValue.create(toDouble() - rValue);
0601:            }
0602:
0603:            /*
0604:             * Bit and.
0605:             */
0606:            @Override
0607:            public Value bitAnd(Value rValue) {
0608:                if (rValue.isString()) {
0609:                    StringValue rStr = (StringValue) rValue;
0610:
0611:                    int len = Math.min(length(), rValue.length());
0612:                    StringValue sb = createStringBuilder();
0613:
0614:                    for (int i = 0; i < len; i++) {
0615:                        char l = charAt(i);
0616:                        char r = rStr.charAt(i);
0617:
0618:                        sb.appendByte(l & r);
0619:                    }
0620:
0621:                    return sb;
0622:                } else
0623:                    return LongValue.create(toLong() & rValue.toLong());
0624:            }
0625:
0626:            /*
0627:             * Bit or.
0628:             */
0629:            @Override
0630:            public Value bitOr(Value rValue) {
0631:                if (rValue.isString()) {
0632:                    StringValue rStr = (StringValue) rValue;
0633:
0634:                    int len = Math.min(length(), rValue.length());
0635:                    StringValue sb = createStringBuilder();
0636:
0637:                    for (int i = 0; i < len; i++) {
0638:                        char l = charAt(i);
0639:                        char r = rStr.charAt(i);
0640:
0641:                        sb.appendByte(l | r);
0642:                    }
0643:
0644:                    if (len != length())
0645:                        sb.append(substring(len));
0646:                    else if (len != rStr.length())
0647:                        sb.append(rStr.substring(len));
0648:
0649:                    return sb;
0650:                } else
0651:                    return LongValue.create(toLong() | rValue.toLong());
0652:            }
0653:
0654:            /*
0655:             * Bit xor.
0656:             */
0657:            @Override
0658:            public Value bitXor(Value rValue) {
0659:                if (rValue.isString()) {
0660:                    StringValue rStr = (StringValue) rValue;
0661:
0662:                    int len = Math.min(length(), rValue.length());
0663:                    StringValue sb = createStringBuilder();
0664:
0665:                    for (int i = 0; i < len; i++) {
0666:                        char l = charAt(i);
0667:                        char r = rStr.charAt(i);
0668:
0669:                        sb.appendByte(l ^ r);
0670:                    }
0671:
0672:                    return sb;
0673:                } else
0674:                    return LongValue.create(toLong() ^ rValue.toLong());
0675:            }
0676:
0677:            /**
0678:             * Serializes the value.
0679:             */
0680:            @Override
0681:            public void serialize(StringBuilder sb) {
0682:                sb.append("s:");
0683:                sb.append(length());
0684:                sb.append(":\"");
0685:                sb.append(toString());
0686:                sb.append("\";");
0687:            }
0688:
0689:            //
0690:            // append code
0691:            //
0692:
0693:            /**
0694:             * Append a Java string to the value.
0695:             */
0696:            public StringValue append(String s) {
0697:                throw new UnsupportedOperationException(getClass().getName());
0698:            }
0699:
0700:            /**
0701:             * Append a Java string to the value.
0702:             */
0703:            public StringValue append(String s, int start, int end) {
0704:                throw new UnsupportedOperationException(getClass().getName());
0705:            }
0706:
0707:            /**
0708:             * Append a Java buffer to the value.
0709:             */
0710:            public StringValue append(char[] buf, int offset, int length) {
0711:                throw new UnsupportedOperationException(getClass().getName());
0712:            }
0713:
0714:            /**
0715:             * Append a Java double to the value.
0716:             */
0717:            public StringValue append(char[] buf) {
0718:                return append(buf, 0, buf.length);
0719:            }
0720:
0721:            /**
0722:             * Append a Java buffer to the value.
0723:             */
0724:            public StringValue append(CharSequence buf, int head, int tail) {
0725:                throw new UnsupportedOperationException(getClass().getName());
0726:            }
0727:
0728:            /**
0729:             * Append a Java buffer to the value.
0730:             */
0731:            public StringValue append(UnicodeBuilderValue sb, int head, int tail) {
0732:                throw new UnsupportedOperationException(getClass().getName());
0733:            }
0734:
0735:            /*
0736:             * Appends a Unicode string to the value.
0737:             * 
0738:             * @param str should be a Unicode string
0739:             * @param charset to decode string from
0740:             */
0741:            public StringValue append(Env env, StringValue unicodeStr,
0742:                    String charset) {
0743:                if (!unicodeStr.isUnicode())
0744:                    return append(unicodeStr);
0745:
0746:                try {
0747:                    byte[] bytes = unicodeStr.toString().getBytes(charset);
0748:
0749:                    append(bytes);
0750:                    return this ;
0751:
0752:                } catch (UnsupportedEncodingException e) {
0753:                    env.warning(e);
0754:
0755:                    return append(unicodeStr);
0756:                }
0757:            }
0758:
0759:            /**
0760:             * Append a Java char to the value.
0761:             */
0762:            public StringValue append(char v) {
0763:                throw new UnsupportedOperationException(getClass().getName());
0764:            }
0765:
0766:            /**
0767:             * Append a Java boolean to the value.
0768:             */
0769:            public StringValue append(boolean v) {
0770:                return append(v ? "true" : "false");
0771:            }
0772:
0773:            /**
0774:             * Append a Java long to the value.
0775:             */
0776:            public StringValue append(long v) {
0777:                return append(String.valueOf(v));
0778:            }
0779:
0780:            /**
0781:             * Append a Java double to the value.
0782:             */
0783:            public StringValue append(double v) {
0784:                return append(String.valueOf(v));
0785:            }
0786:
0787:            /**
0788:             * Append a Java value to the value.
0789:             */
0790:            public StringValue append(Object v) {
0791:                return append(String.valueOf(v));
0792:            }
0793:
0794:            /**
0795:             * Append a Java value to the value.
0796:             */
0797:            public StringValue append(Value v) {
0798:                throw new UnsupportedOperationException(getClass().getName());
0799:            }
0800:
0801:            /**
0802:             * Ensure enough append capacity.
0803:             */
0804:            public void ensureAppendCapacity(int size) {
0805:                throw new UnsupportedOperationException(getClass().getName());
0806:            }
0807:
0808:            /**
0809:             * Append a byte buffer to the value.
0810:             */
0811:            public StringValue append(byte[] buf, int offset, int length) {
0812:                throw new UnsupportedOperationException(getClass().getName());
0813:            }
0814:
0815:            /**
0816:             * Append a byte buffer to the value.
0817:             */
0818:            public StringValue append(byte[] buf) {
0819:                return append(buf, 0, buf.length);
0820:            }
0821:
0822:            /**
0823:             * Append to a string builder.
0824:             */
0825:            @Override
0826:            public StringValue appendTo(UnicodeBuilderValue sb) {
0827:                int length = length();
0828:
0829:                for (int i = 0; i < length; i++)
0830:                    sb.append(charAt(i));
0831:
0832:                return this ;
0833:            }
0834:
0835:            /**
0836:             * Append a Java boolean to the value.
0837:             */
0838:            public StringValue appendUnicode(boolean v) {
0839:                return append(v ? "true" : "false");
0840:            }
0841:
0842:            /**
0843:             * Append a Java long to the value.
0844:             */
0845:            public StringValue appendUnicode(long v) {
0846:                return append(String.valueOf(v));
0847:            }
0848:
0849:            /**
0850:             * Append a Java double to the value.
0851:             */
0852:            public StringValue appendUnicode(double v) {
0853:                return append(String.valueOf(v));
0854:            }
0855:
0856:            /**
0857:             * Append a Java value to the value.
0858:             */
0859:            public StringValue appendUnicode(Object v) {
0860:                return append(String.valueOf(v));
0861:            }
0862:
0863:            /**
0864:             * Append a Java char, possibly converting to a unicode string
0865:             */
0866:            public StringValue appendUnicode(char v) {
0867:                return append(v);
0868:            }
0869:
0870:            /**
0871:             * Append a Java char buffer, possibly converting to a unicode string
0872:             */
0873:            public StringValue appendUnicode(char[] buffer, int offset,
0874:                    int length) {
0875:                return append(buffer, offset, length);
0876:            }
0877:
0878:            /**
0879:             * Append a Java char buffer, possibly converting to a unicode string
0880:             */
0881:            public StringValue appendUnicode(char[] buffer) {
0882:                return append(buffer);
0883:            }
0884:
0885:            /**
0886:             * Append a Java char buffer, possibly converting to a unicode string
0887:             */
0888:            public StringValue appendUnicode(String value) {
0889:                return append(value);
0890:            }
0891:
0892:            /**
0893:             * Append a Java char buffer, possibly converting to a unicode string
0894:             */
0895:            public StringValue appendUnicode(String value, int offset,
0896:                    int length) {
0897:                return append(value, offset, length);
0898:            }
0899:
0900:            /**
0901:             * Append a Java char buffer, possibly converting to a unicode string
0902:             */
0903:            public StringValue appendUnicode(Value value) {
0904:                return append(value);
0905:            }
0906:
0907:            /**
0908:             * Append a Java char buffer, possibly converting to a unicode string
0909:             */
0910:            public StringValue appendUnicode(Value v1, Value v2) {
0911:                return append(v1).append(v2);
0912:            }
0913:
0914:            /**
0915:             * Append a Java byte to the value without conversions.
0916:             */
0917:            public StringValue appendByte(int v) {
0918:                throw new UnsupportedOperationException(getClass().getName());
0919:            }
0920:
0921:            /**
0922:             * Append a Java String to the value without conversions.
0923:             */
0924:            public StringValue appendBytes(String s) {
0925:                StringValue sb = this ;
0926:
0927:                for (int i = 0; i < s.length(); i++) {
0928:                    sb = sb.appendByte(s.charAt(i));
0929:                }
0930:
0931:                return sb;
0932:            }
0933:
0934:            /**
0935:             * Append a Java char[] to the value without conversions.
0936:             */
0937:            public StringValue appendBytes(char[] buf, int offset, int length) {
0938:                StringValue sb = this ;
0939:                int end = Math.min(buf.length, offset + length);
0940:
0941:                while (offset < end) {
0942:                    sb = sb.appendByte(buf[offset++]);
0943:                }
0944:
0945:                return sb;
0946:            }
0947:
0948:            /**
0949:             * Append from a read stream
0950:             */
0951:            public StringValue append(Reader reader) throws IOException {
0952:                int ch;
0953:
0954:                while ((ch = reader.read()) >= 0) {
0955:                    append((char) ch);
0956:                }
0957:
0958:                return this ;
0959:            }
0960:
0961:            /**
0962:             * Append from a read stream
0963:             */
0964:            public StringValue append(Reader reader, long length)
0965:                    throws IOException {
0966:                int ch;
0967:
0968:                while (length-- > 0 && (ch = reader.read()) >= 0) {
0969:                    append((char) ch);
0970:                }
0971:
0972:                return this ;
0973:            }
0974:
0975:            /**
0976:             * Append from an input stream, using InputStream.read semantics,
0977:             * i.e. just call is.read once even if more data is available.
0978:             */
0979:            public int appendRead(InputStream is, long length) {
0980:                TempBuffer tBuf = TempBuffer.allocate();
0981:
0982:                try {
0983:                    byte[] buffer = tBuf.getBuffer();
0984:                    int sublen = buffer.length;
0985:                    if (length < sublen)
0986:                        sublen = (int) length;
0987:
0988:                    sublen = is.read(buffer, 0, sublen);
0989:
0990:                    if (sublen > 0)
0991:                        append(buffer, 0, sublen);
0992:
0993:                    return sublen;
0994:                } catch (IOException e) {
0995:                    throw new QuercusModuleException(e);
0996:                } finally {
0997:                    TempBuffer.free(tBuf);
0998:                }
0999:            }
1000:
1001:            /**
1002:             * Append from an input stream, reading from the input stream until
1003:             * end of file or the length is reached.
1004:             */
1005:            public int appendReadAll(InputStream is, long length) {
1006:                TempBuffer tBuf = TempBuffer.allocate();
1007:
1008:                try {
1009:                    byte[] buffer = tBuf.getBuffer();
1010:                    int readLength = 0;
1011:
1012:                    while (length > 0) {
1013:                        int sublen = buffer.length;
1014:                        if (length < sublen)
1015:                            sublen = (int) length;
1016:
1017:                        sublen = is.read(buffer, 0, sublen);
1018:
1019:                        if (sublen > 0) {
1020:                            append(buffer, 0, sublen);
1021:                            length -= sublen;
1022:                            readLength += sublen;
1023:                        } else
1024:                            return readLength > 0 ? readLength : -1;
1025:                    }
1026:
1027:                    return readLength;
1028:                } catch (IOException e) {
1029:                    throw new QuercusModuleException(e);
1030:                } finally {
1031:                    TempBuffer.free(tBuf);
1032:                }
1033:            }
1034:
1035:            /**
1036:             * Append from an input stream, using InputStream semantics, i.e
1037:             * call is.read() only once.
1038:             */
1039:            public int appendRead(BinaryInput is, long length) {
1040:                TempBuffer tBuf = TempBuffer.allocate();
1041:
1042:                try {
1043:                    byte[] buffer = tBuf.getBuffer();
1044:                    int sublen = buffer.length;
1045:                    if (length < sublen)
1046:                        sublen = (int) length;
1047:                    else if (length > sublen) {
1048:                        buffer = new byte[(int) length];
1049:                        sublen = (int) length;
1050:                    }
1051:
1052:                    sublen = is.read(buffer, 0, sublen);
1053:
1054:                    if (sublen > 0)
1055:                        append(buffer, 0, sublen);
1056:
1057:                    return sublen;
1058:                } catch (IOException e) {
1059:                    throw new QuercusModuleException(e);
1060:                } finally {
1061:                    TempBuffer.free(tBuf);
1062:                }
1063:            }
1064:
1065:            /**
1066:             * Append from an input stream, reading all available data from the
1067:             * stream.
1068:             */
1069:            public int appendReadAll(BinaryInput is, long length) {
1070:                TempBuffer tBuf = TempBuffer.allocate();
1071:
1072:                try {
1073:                    byte[] buffer = tBuf.getBuffer();
1074:                    int readLength = 0;
1075:
1076:                    while (length > 0) {
1077:                        int sublen = buffer.length;
1078:                        if (length < sublen)
1079:                            sublen = (int) length;
1080:
1081:                        sublen = is.read(buffer, 0, sublen);
1082:
1083:                        if (sublen > 0) {
1084:                            append(buffer, 0, sublen);
1085:                            length -= sublen;
1086:                            readLength += sublen;
1087:                        } else
1088:                            return readLength > 0 ? readLength : -1;
1089:                    }
1090:
1091:                    return readLength;
1092:                } catch (IOException e) {
1093:                    throw new QuercusModuleException(e);
1094:                } finally {
1095:                    TempBuffer.free(tBuf);
1096:                }
1097:            }
1098:
1099:            /**
1100:             * Exports the value.
1101:             */
1102:            @Override
1103:            public void varExport(StringBuilder sb) {
1104:                sb.append("'");
1105:
1106:                String value = toString();
1107:                int len = value.length();
1108:                for (int i = 0; i < len; i++) {
1109:                    char ch = value.charAt(i);
1110:
1111:                    switch (ch) {
1112:                    case '\'':
1113:                        sb.append("\\'");
1114:                        break;
1115:                    case '\\':
1116:                        sb.append("\\\\");
1117:                        break;
1118:                    default:
1119:                        sb.append(ch);
1120:                    }
1121:                }
1122:                sb.append("'");
1123:            }
1124:
1125:            /**
1126:             * Interns the string.
1127:             */
1128:            public StringValue intern(Quercus quercus) {
1129:                return quercus.intern(toString());
1130:            }
1131:
1132:            //
1133:            // CharSequence
1134:            //
1135:
1136:            /**
1137:             * Returns the length of the string.
1138:             */
1139:            public int length() {
1140:                return toString().length();
1141:            }
1142:
1143:            /**
1144:             * Returns the character at a particular location
1145:             */
1146:            public char charAt(int index) {
1147:                return toString().charAt(index);
1148:            }
1149:
1150:            /**
1151:             * Returns a subsequence
1152:             */
1153:            public CharSequence subSequence(int start, int end) {
1154:                return new StringBuilderValue(toString().substring(start, end));
1155:            }
1156:
1157:            //
1158:            // java.lang.String methods
1159:            //
1160:
1161:            /**
1162:             * Returns the first index of the match string, starting from the head.
1163:             */
1164:            public final int indexOf(CharSequence match) {
1165:                return indexOf(match, 0);
1166:            }
1167:
1168:            /**
1169:             * Returns the first index of the match string, starting from the head.
1170:             */
1171:            public int indexOf(CharSequence match, int head) {
1172:                int length = length();
1173:                int matchLength = match.length();
1174:
1175:                if (matchLength <= 0)
1176:                    return -1;
1177:                else if (head < 0)
1178:                    return -1;
1179:
1180:                int end = length - matchLength;
1181:                char first = match.charAt(0);
1182:
1183:                loop: for (; head <= end; head++) {
1184:                    if (charAt(head) != first)
1185:                        continue;
1186:
1187:                    for (int i = 1; i < matchLength; i++) {
1188:                        if (charAt(head + i) != match.charAt(i))
1189:                            continue loop;
1190:                    }
1191:
1192:                    return head;
1193:                }
1194:
1195:                return -1;
1196:            }
1197:
1198:            /**
1199:             * Returns the last index of the match string, starting from the head.
1200:             */
1201:            public int indexOf(char match) {
1202:                return indexOf(match, 0);
1203:            }
1204:
1205:            /**
1206:             * Returns the last index of the match string, starting from the head.
1207:             */
1208:            public int indexOf(char match, int head) {
1209:                int length = length();
1210:
1211:                for (; head < length; head++) {
1212:                    if (charAt(head) == match)
1213:                        return head;
1214:                }
1215:
1216:                return -1;
1217:            }
1218:
1219:            /**
1220:             * Returns the last index of the match string, starting from the head.
1221:             */
1222:            public final int lastIndexOf(char match) {
1223:                return lastIndexOf(match, Integer.MAX_VALUE);
1224:            }
1225:
1226:            /**
1227:             * Returns the last index of the match string, starting from the head.
1228:             */
1229:            public int lastIndexOf(char match, int tail) {
1230:                int length = length();
1231:
1232:                if (tail >= length)
1233:                    tail = length - 1;
1234:
1235:                for (; tail >= 0; tail--) {
1236:                    if (charAt(tail) == match)
1237:                        return tail;
1238:                }
1239:
1240:                return -1;
1241:            }
1242:
1243:            /**
1244:             * Returns the last index of the match string, starting from the tail.
1245:             */
1246:            public int lastIndexOf(CharSequence match) {
1247:                return lastIndexOf(match, Integer.MAX_VALUE);
1248:            }
1249:
1250:            /**
1251:             * Returns the last index of the match string, starting from the tail.
1252:             */
1253:            public int lastIndexOf(CharSequence match, int tail) {
1254:                int length = length();
1255:                int matchLength = match.length();
1256:
1257:                if (matchLength <= 0)
1258:                    return -1;
1259:                if (tail < 0)
1260:                    return -1;
1261:
1262:                if (tail > length - matchLength)
1263:                    tail = length - matchLength;
1264:
1265:                char first = match.charAt(0);
1266:
1267:                loop: for (; tail >= 0; tail--) {
1268:                    if (charAt(tail) != first)
1269:                        continue;
1270:
1271:                    for (int i = 1; i < matchLength; i++) {
1272:                        if (charAt(tail + i) != match.charAt(i))
1273:                            continue loop;
1274:                    }
1275:
1276:                    return tail;
1277:                }
1278:
1279:                return -1;
1280:            }
1281:
1282:            /**
1283:             * Returns true if the region matches
1284:             */
1285:            public boolean regionMatches(int offset, char[] mBuffer,
1286:                    int mOffset, int mLength) {
1287:                int length = length();
1288:
1289:                if (length < offset + mLength)
1290:                    return false;
1291:
1292:                for (int i = 0; i < mLength; i++) {
1293:                    if (charAt(offset + i) != mBuffer[mOffset + i])
1294:                        return false;
1295:                }
1296:
1297:                return true;
1298:            }
1299:
1300:            /**
1301:             * Returns true if the region matches
1302:             */
1303:            public boolean regionMatches(int offset, StringValue match,
1304:                    int mOffset, int mLength) {
1305:                int length = length();
1306:
1307:                if (length < offset + mLength)
1308:                    return false;
1309:
1310:                for (int i = 0; i < mLength; i++) {
1311:                    if (charAt(offset + i) != match.charAt(mOffset + i))
1312:                        return false;
1313:                }
1314:
1315:                return true;
1316:            }
1317:
1318:            /**
1319:             * Returns true if the region matches
1320:             */
1321:            public boolean regionMatchesIgnoreCase(int offset, char[] match,
1322:                    int mOffset, int mLength) {
1323:                int length = length();
1324:
1325:                if (length < offset + mLength)
1326:                    return false;
1327:
1328:                for (int i = 0; i < mLength; i++) {
1329:                    char a = Character.toLowerCase(charAt(offset + i));
1330:                    char b = Character.toLowerCase(match[mOffset + i]);
1331:
1332:                    if (a != b)
1333:                        return false;
1334:                }
1335:
1336:                return true;
1337:            }
1338:
1339:            /**
1340:             * Returns true if the string ends with another string.
1341:             */
1342:            public boolean endsWith(StringValue tail) {
1343:                int len = length();
1344:                int tailLen = tail.length();
1345:
1346:                int offset = len - tailLen;
1347:
1348:                if (offset < 0)
1349:                    return false;
1350:
1351:                for (int i = 0; i < tailLen; i++) {
1352:                    if (charAt(offset + i) != tail.charAt(i))
1353:                        return false;
1354:                }
1355:
1356:                return true;
1357:            }
1358:
1359:            /**
1360:             * Returns a StringValue substring.
1361:             */
1362:            public StringValue substring(int head) {
1363:                return (StringValue) subSequence(head, length());
1364:            }
1365:
1366:            /**
1367:             * Returns a StringValue substring.
1368:             */
1369:            public StringValue substring(int begin, int end) {
1370:                return (StringValue) subSequence(begin, end);
1371:            }
1372:
1373:            /**
1374:             * Returns a character array
1375:             */
1376:            public char[] toCharArray() {
1377:                int length = length();
1378:
1379:                char[] array = new char[length()];
1380:
1381:                getChars(0, array, 0, length);
1382:
1383:                return array;
1384:            }
1385:
1386:            public char[] getRawCharArray() {
1387:                return toCharArray();
1388:            }
1389:
1390:            /**
1391:             * Copies the chars
1392:             */
1393:            public void getChars(int stringOffset, char[] buffer, int offset,
1394:                    int length) {
1395:                for (int i = 0; i < length; i++)
1396:                    buffer[offset + i] = charAt(stringOffset + i);
1397:            }
1398:
1399:            /**
1400:             * Convert to lower case.
1401:             */
1402:            public StringValue toLowerCase() {
1403:                int length = length();
1404:
1405:                UnicodeBuilderValue string = new UnicodeBuilderValue(length);
1406:
1407:                char[] buffer = string.getBuffer();
1408:                getChars(0, buffer, 0, length);
1409:
1410:                for (int i = 0; i < length; i++) {
1411:                    char ch = buffer[i];
1412:
1413:                    if ('A' <= ch && ch <= 'Z')
1414:                        buffer[i] = (char) (ch + 'a' - 'A');
1415:                    else if (ch < 0x80) {
1416:                    } else if (Character.isUpperCase(ch))
1417:                        buffer[i] = Character.toLowerCase(ch);
1418:                }
1419:
1420:                string.setOffset(length);
1421:
1422:                return string;
1423:            }
1424:
1425:            /**
1426:             * Convert to lower case.
1427:             */
1428:            public StringValue toUpperCase() {
1429:                int length = length();
1430:
1431:                UnicodeBuilderValue string = new UnicodeBuilderValue(length);
1432:
1433:                char[] buffer = string.getBuffer();
1434:                getChars(0, buffer, 0, length);
1435:
1436:                for (int i = 0; i < length; i++) {
1437:                    char ch = buffer[i];
1438:
1439:                    if ('a' <= ch && ch <= 'z')
1440:                        buffer[i] = (char) (ch + 'A' - 'a');
1441:                    else if (ch < 0x80) {
1442:                    } else if (Character.isLowerCase(ch))
1443:                        buffer[i] = Character.toUpperCase(ch);
1444:                }
1445:
1446:                string.setOffset(length);
1447:
1448:                return string;
1449:            }
1450:
1451:            /**
1452:             * Returns a byteArrayInputStream for the value.
1453:             * See TempBufferStringValue for how this can be overriden
1454:             *
1455:             * @return InputStream
1456:             */
1457:            public InputStream toInputStream() {
1458:                try {
1459:                    //XXX: refactor so that env is passed in
1460:                    return toInputStream(Env.getInstance().getRuntimeEncoding());
1461:                } catch (UnsupportedEncodingException e) {
1462:                    throw new QuercusRuntimeException(e);
1463:                }
1464:                //return new StringValueInputStream();
1465:            }
1466:
1467:            /**
1468:             * Returns a byte stream of chars.
1469:             * @param charset to encode chars to
1470:             */
1471:            public InputStream toInputStream(String charset)
1472:                    throws UnsupportedEncodingException {
1473:                return new ByteArrayInputStream(toString().getBytes(charset));
1474:            }
1475:
1476:            /**
1477:             * Returns a char stream.
1478:             * XXX: when decoding fails
1479:             *
1480:             * @param charset to decode bytes by
1481:             */
1482:            public Reader toReader(String charset)
1483:                    throws UnsupportedEncodingException {
1484:                byte[] bytes = toBytes();
1485:
1486:                return new InputStreamReader(new ByteArrayInputStream(bytes),
1487:                        charset);
1488:            }
1489:
1490:            /**
1491:             * Converts to a BinaryValue in desired charset.
1492:             *
1493:             * @param env
1494:             * @param charset
1495:             */
1496:            public StringValue toBinaryValue(Env env, String charset) {
1497:                TempBuffer tb = TempBuffer.allocate();
1498:                byte[] buffer = tb.getBuffer();
1499:
1500:                try {
1501:                    InputStream in = toInputStream(charset);
1502:                    TempStream out = new TempStream();
1503:
1504:                    int sublen = in.read(buffer, 0, buffer.length);
1505:
1506:                    while (sublen >= 0) {
1507:                        out.write(buffer, 0, sublen, false);
1508:                        sublen = in.read(buffer, 0, buffer.length);
1509:                    }
1510:
1511:                    out.flush();
1512:
1513:                    StringValue result = env.createBinaryBuilder();
1514:                    for (TempBuffer ptr = out.getHead(); ptr != null; ptr = ptr
1515:                            .getNext()) {
1516:                        result.append(ptr.getBuffer(), 0, ptr.getLength());
1517:                    }
1518:
1519:                    TempBuffer.free(out.getHead());
1520:
1521:                    return result;
1522:                } catch (IOException e) {
1523:                    throw new QuercusModuleException(e.getMessage());
1524:                } finally {
1525:                    TempBuffer.free(tb);
1526:                }
1527:            }
1528:
1529:            public byte[] toBytes() {
1530:                throw new UnsupportedOperationException();
1531:            }
1532:
1533:            /**
1534:             * Decodes from charset and returns UnicodeValue.
1535:             *
1536:             * @param env
1537:             * @param charset
1538:             */
1539:            public StringValue toUnicodeValue(Env env, String charset) {
1540:                StringValue sb = env.createUnicodeBuilder();
1541:
1542:                TempCharBuffer tb = TempCharBuffer.allocate();
1543:                char[] charBuf = tb.getBuffer();
1544:
1545:                try {
1546:                    Reader in = toReader(charset);
1547:
1548:                    int sublen;
1549:                    while ((sublen = in.read(charBuf, 0, charBuf.length)) >= 0) {
1550:                        sb.append(charBuf, 0, sublen);
1551:                    }
1552:
1553:                } catch (IOException e) {
1554:                    throw new QuercusModuleException(e.getMessage());
1555:
1556:                } finally {
1557:                    TempCharBuffer.free(tb);
1558:                }
1559:
1560:                return sb;
1561:            }
1562:
1563:            /**
1564:             * Decodes from charset and returns UnicodeValue.
1565:             *
1566:             * @param env
1567:             * @param charset
1568:             */
1569:            public StringValue convertToUnicode(Env env, String charset) {
1570:                UnicodeBuilderValue sb = new UnicodeBuilderValue();
1571:
1572:                TempCharBuffer tb = TempCharBuffer.allocate();
1573:                char[] charBuf = tb.getBuffer();
1574:
1575:                try {
1576:                    Reader in = toReader(charset);
1577:
1578:                    int sublen;
1579:                    while ((sublen = in.read(charBuf, 0, charBuf.length)) >= 0) {
1580:                        sb.append(charBuf, 0, sublen);
1581:                    }
1582:
1583:                } catch (IOException e) {
1584:                    throw new QuercusModuleException(e.getMessage());
1585:
1586:                } finally {
1587:                    TempCharBuffer.free(tb);
1588:                }
1589:
1590:                return sb;
1591:            }
1592:
1593:            /**
1594:             * Converts to a string builder
1595:             */
1596:            @Override
1597:            public StringValue toStringBuilder(Env env) {
1598:                return createStringBuilder().append(this );
1599:            }
1600:
1601:            /**
1602:             * Writes to a stream
1603:             */
1604:            public void writeTo(OutputStream os) {
1605:                try {
1606:                    int len = length();
1607:
1608:                    for (int i = 0; i < len; i++)
1609:                        os.write(charAt(i));
1610:                } catch (IOException e) {
1611:                    throw new QuercusModuleException(e);
1612:                }
1613:            }
1614:
1615:            //
1616:            // java.lang.Object methods
1617:            //
1618:
1619:            /**
1620:             * Returns the hash code.
1621:             */
1622:            public int hashCode() {
1623:                int hash = 37;
1624:
1625:                int length = length();
1626:
1627:                for (int i = 0; i < length; i++) {
1628:                    hash = 65521 * hash + charAt(i);
1629:                }
1630:
1631:                return hash;
1632:            }
1633:
1634:            /**
1635:             * Test for equality
1636:             */
1637:            public boolean equals(Object o) {
1638:                if (this  == o)
1639:                    return true;
1640:                else if (!(o instanceof  StringValue))
1641:                    return false;
1642:
1643:                StringValue s = (StringValue) o;
1644:
1645:                if (s.isUnicode() != isUnicode())
1646:                    return false;
1647:
1648:                int aLength = length();
1649:                int bLength = s.length();
1650:
1651:                if (aLength != bLength)
1652:                    return false;
1653:
1654:                for (int i = aLength - 1; i >= 0; i--) {
1655:                    if (charAt(i) != s.charAt(i))
1656:                        return false;
1657:                }
1658:
1659:                return true;
1660:            }
1661:
1662:            @Override
1663:            abstract public String toDebugString();
1664:
1665:            @Override
1666:            abstract public void varDumpImpl(Env env, WriteStream out,
1667:                    int depth, IdentityHashMap<Value, String> valueSet)
1668:                    throws IOException;
1669:
1670:            class StringValueInputStream extends java.io.InputStream {
1671:                private final int _length;
1672:                private int _index;
1673:
1674:                StringValueInputStream() {
1675:                    _length = length();
1676:                }
1677:
1678:                /**
1679:                 * Reads the next byte.
1680:                 */
1681:                public int read() {
1682:                    if (_index < _length)
1683:                        return charAt(_index++);
1684:                    else
1685:                        return -1;
1686:                }
1687:
1688:                /**
1689:                 * Reads into a buffer.
1690:                 */
1691:                public int read(byte[] buffer, int offset, int length) {
1692:                    int sublen = _length - _index;
1693:
1694:                    if (length < sublen)
1695:                        sublen = length;
1696:
1697:                    if (sublen <= 0)
1698:                        return -1;
1699:
1700:                    int index = _index;
1701:
1702:                    for (int i = 0; i < sublen; i++)
1703:                        buffer[offset + i] = (byte) charAt(index + i);
1704:
1705:                    _index += sublen;
1706:
1707:                    return sublen;
1708:                }
1709:            }
1710:
1711:            static {
1712:                // XXX: need to update for unicode
1713:
1714:                CHAR_STRINGS = new StringValue[256];
1715:
1716:                for (int i = 0; i < CHAR_STRINGS.length; i++)
1717:                    CHAR_STRINGS[i] = new StringBuilderValue(String
1718:                            .valueOf((char) i));
1719:            }
1720:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.