Source Code Cross Referenced for FormatCmd.java in  » Scripting » jacl » tcl » lang » 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 » Scripting » jacl » tcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * FormatCmd.java
0003:         *
0004:         * Copyright (c) 1997 Sun Microsystems, Inc.
0005:         *
0006:         * See the file "license.terms" for information on usage and
0007:         * redistribution of this file, and for a DISCLAIMER OF ALL
0008:         * WARRANTIES.
0009:         * 
0010:         * RCS: @(#) $Id: FormatCmd.java,v 1.13 2006/05/14 22:07:49 mdejong Exp $
0011:         *
0012:         */
0013:
0014:        package tcl.lang;
0015:
0016:        import java.util.*;
0017:
0018:        /**
0019:         * This class implements the built-in "format" command in Tcl.
0020:         */
0021:
0022:        class FormatCmd implements  Command {
0023:
0024:            private static final int LEFT_JUSTIFY = 1;
0025:            private static final int SHOW_SIGN = 2;
0026:            private static final int SPACE_OR_SIGN = 4;
0027:            private static final int PAD_W_ZERO = 8;
0028:            private static final int ALT_OUTPUT = 16;
0029:            private static final int SIGNED_VALUE = 32;
0030:            private static final int RADIX = 1; // Integer types.  %d, %x, %o
0031:            private static final int FLOAT = 2; // Floating point.  %f
0032:            private static final int EXP = 3; // Exponentional. %e and %E
0033:            private static final int GENERIC = 4; // Floating or exponential, 
0034:
0035:            // depending on exponent. %g
0036:
0037:            /**
0038:             * This procedure is invoked to process the "format" Tcl command.
0039:             * See the user documentation for details on what it does.
0040:             *
0041:             * The first argument to the cmdProc is the formatString.  The cmdProc
0042:             * simply copies all the chars into the sbuf until a '%' is found.  At
0043:             * this point the cmdProc parces the formatString and determines the 
0044:             * format parameters.  The parcing of the formatString can be broken into
0045:             * six possible phases:
0046:             * 
0047:             * Phase 0 - Simply Print:            If the next char is %
0048:             * Phase 1 - XPG3 Position Specifier: If the format [1-n]$ is used
0049:             * Phase 2 - A Set of Flags:          One or more of the following + - 
0050:             *                                           [space] 0 # 
0051:             * Phase 3 - A Minimun Field Width    Either [integer] or *
0052:             * Phase 4 - A Precision              If the format .[integer] or .*
0053:             * Phase 5 - A Length Modifier        If h is present
0054:             * Phase 6 - A Conversion Character   If one of the following is used
0055:             *                                    d u i o x X c s f E g G
0056:             * 
0057:             * Any phase can skip ahead one or more phases, but are not allowed 
0058:             * to move back to previous phases.  Once the parameters are determined
0059:             * the cmdProc calls one of three private methods that returns a fully
0060:             * formatted string.  This loop occurs for ever '%' in the formatString.
0061:             */
0062:
0063:            public void cmdProc(Interp interp, TclObject argv[])
0064:                    throws TclException {
0065:
0066:                StringBuffer sbuf; // Stores the return value of the parsed
0067:                // format string
0068:                StrtoulResult stoul; // A result object to pass to strtoul call
0069:                char[] format; // The format argument is converted to a char 
0070:                // array and manipulated as such
0071:                int phase; // Stores the current phase of the parsing
0072:                int width; // Minimum field width
0073:                int precision; // Field precision from field specifier
0074:                int fmtFlags; // Used to store the format flags ( #,+,etc)
0075:                int argIndex; // Index of argument to substitute next.
0076:                int fmtIndex; // Used to locate end of the format fields.
0077:                int endIndex; // Used to locate end of numerical fields.
0078:                int intValue; // Generic storage variable
0079:                long lngValue; // Store the TclInteger.get() result
0080:                double dblValue; // Store the TclDouble.get() result
0081:                boolean noPercent; // Special case for speed:  indicates there's
0082:                // no field specifier, just a string to copy.
0083:                boolean xpgSet; // Indicates that xpg has been used for the 
0084:                // particular format of the main while loop
0085:                boolean gotXpg; // True means that an XPG3 %n$-style
0086:                // specifier has been seen.
0087:                boolean gotSequential; // True means that a regular sequential
0088:                // (non-XPG3) conversion specifier has
0089:                // been seen.
0090:                boolean useShort; // Value to be printed is short 
0091:                // (half word).
0092:                boolean precisionSet; // Used for f, e, and E conversions
0093:                boolean cont; // Used for phase 3
0094:
0095:                if (argv.length < 2) {
0096:                    throw new TclNumArgsException(interp, 1, argv,
0097:                            "formatString ?arg arg ...?");
0098:                }
0099:
0100:                argIndex = 2;
0101:                fmtIndex = 0;
0102:                gotXpg = gotSequential = false;
0103:                format = argv[1].toString().toCharArray();
0104:                sbuf = new StringBuffer();
0105:
0106:                // So, what happens here is to scan the format string one % group
0107:                // at a time, making many individual appends to the StringBuffer.
0108:
0109:                while (fmtIndex < format.length) {
0110:                    fmtFlags = phase = width = 0;
0111:                    noPercent = true;
0112:                    xpgSet = precisionSet = useShort = false;
0113:                    precision = -1;
0114:
0115:                    // Append all characters to sbuf that are not used for the
0116:                    // format specifier.
0117:
0118:                    if (format[fmtIndex] != '%') {
0119:                        int i;
0120:                        for (i = fmtIndex; (i < format.length); i++) {
0121:                            if (format[i] == '%') {
0122:                                noPercent = false;
0123:                                break;
0124:                            }
0125:                        }
0126:                        sbuf.append(new String(format, fmtIndex, i - fmtIndex));
0127:                        fmtIndex = i;
0128:                        if (noPercent) {
0129:                            break;
0130:                        }
0131:                    }
0132:
0133:                    // If true, then a % has been indicated but we are at the end
0134:                    // of the format string.  Call function to throw exception.
0135:
0136:                    if (fmtIndex + 1 >= format.length) {
0137:                        errorEndMiddle(interp);
0138:                    }
0139:
0140:                    // Phase 0:
0141:                    // Check for %%.  If true then simply write a single '%'
0142:                    // to the list.
0143:
0144:                    checkOverFlow(interp, format, fmtIndex + 1);
0145:                    if (format[fmtIndex + 1] == '%') {
0146:                        sbuf.append("%");
0147:                        fmtIndex += 2;
0148:                        // Re-enter the loop 
0149:
0150:                        continue;
0151:                    }
0152:
0153:                    fmtIndex++;
0154:                    checkOverFlow(interp, format, fmtIndex);
0155:                    if (Character.isDigit(format[fmtIndex])) {
0156:                        // Parse the format array looking for the end of
0157:                        // the number. 
0158:
0159:                        stoul = FormatCmd.strtoul(interp, format, fmtIndex);
0160:                        intValue = (int) stoul.value;
0161:                        endIndex = stoul.index;
0162:                        stoul = null;
0163:
0164:                        if (format[endIndex] == '$') {
0165:                            if (intValue == 0) {
0166:                                errorBadIndex(interp, true);
0167:                            }
0168:
0169:                            // Phase 1:
0170:                            // Check for an XPG3-style %n$ specification.  
0171:                            // Note: there must not be a mixture of XPG3
0172:                            // specs and non-XPG3 specs in the same format string.
0173:
0174:                            if (gotSequential) {
0175:                                errorMixedXPG(interp);
0176:                            }
0177:                            gotXpg = true;
0178:                            xpgSet = true;
0179:                            phase = 2;
0180:                            fmtIndex = endIndex + 1;
0181:                            argIndex = intValue + 1;
0182:                            if ((argIndex < 2) || (argIndex >= argv.length)) {
0183:                                errorBadIndex(interp, gotXpg);
0184:                            }
0185:
0186:                        } else {
0187:                            // Phase 3:
0188:                            // Format jumped straight to phase 3; Setting 
0189:                            // width field.  Again, verify that all format
0190:                            // specifiers are sequential.
0191:
0192:                            if (gotXpg) {
0193:                                errorMixedXPG(interp);
0194:                            }
0195:                            gotSequential = true;
0196:                            if (format[fmtIndex] != '0') {
0197:                                fmtIndex = endIndex;
0198:                                width = intValue;
0199:                                phase = 4;
0200:                            }
0201:                        }
0202:                    } else {
0203:                        if (gotXpg) {
0204:                            errorMixedXPG(interp);
0205:                        }
0206:                        gotSequential = true;
0207:                    }
0208:
0209:                    // Phase 2:
0210:                    // Setting the Format Flags.  At this point the phase value
0211:                    // can be either zero or three.  Anything greater is an
0212:                    // incorrect format.
0213:
0214:                    if (phase < 3) {
0215:                        checkOverFlow(interp, format, fmtIndex);
0216:                        char ch = format[fmtIndex];
0217:                        cont = true;
0218:                        while (cont) {
0219:                            switch (ch) {
0220:                            case '-': {
0221:                                fmtFlags |= LEFT_JUSTIFY;
0222:                                break;
0223:                            }
0224:                            case '#': {
0225:                                fmtFlags |= ALT_OUTPUT;
0226:                                break;
0227:                            }
0228:                            case '0': {
0229:                                fmtFlags |= PAD_W_ZERO;
0230:                                break;
0231:                            }
0232:                            case ' ': {
0233:                                fmtFlags |= SPACE_OR_SIGN;
0234:                                break;
0235:                            }
0236:                            case '+': {
0237:                                fmtFlags |= SHOW_SIGN;
0238:                                break;
0239:                            }
0240:                            default: {
0241:                                cont = false;
0242:                            }
0243:                            }
0244:                            if (cont) {
0245:                                fmtIndex++;
0246:                                checkOverFlow(interp, format, fmtIndex);
0247:                                ch = format[fmtIndex];
0248:                            }
0249:                        }
0250:                        phase = 3;
0251:                    }
0252:
0253:                    // Phase 3:
0254:                    // Setting width field.  Partially redundant code from the
0255:                    // Phase 1 if/else statement, but this is made to run fast.
0256:
0257:                    checkOverFlow(interp, format, fmtIndex);
0258:                    if (Character.isDigit(format[fmtIndex])) {
0259:                        stoul = FormatCmd.strtoul(interp, format, fmtIndex);
0260:                        width = (int) stoul.value;
0261:                        fmtIndex = stoul.index;
0262:                        stoul = null;
0263:                    } else if (format[fmtIndex] == '*') {
0264:                        if (argv.length > argIndex) {
0265:                            width = TclInteger.get(interp, argv[argIndex]);
0266:                            if (width < 0) {
0267:                                width = -width;
0268:                                fmtFlags |= LEFT_JUSTIFY;
0269:                            }
0270:                            argIndex++;
0271:                            fmtIndex++;
0272:                        }
0273:                    }
0274:
0275:                    // Phase 4:
0276:                    // Setting the precision field.
0277:
0278:                    checkOverFlow(interp, format, fmtIndex);
0279:                    if (format[fmtIndex] == '.') {
0280:                        fmtIndex++;
0281:                        checkOverFlow(interp, format, fmtIndex);
0282:                        if (Character.isDigit(format[fmtIndex])) {
0283:                            precisionSet = true;
0284:                            stoul = FormatCmd.strtoul(interp, format, fmtIndex);
0285:                            precision = (int) stoul.value;
0286:                            fmtIndex = stoul.index;
0287:                            stoul = null;
0288:                        } else if (format[fmtIndex] == '*') {
0289:                            if (argv.length > argIndex) {
0290:                                precisionSet = true;
0291:                                precision = TclInteger.get(interp,
0292:                                        argv[argIndex]);
0293:                                argIndex++;
0294:                                fmtIndex++;
0295:                                checkOverFlow(interp, format, fmtIndex);
0296:                            }
0297:                        } else {
0298:                            // Format field had a '.' without an integer or '*'
0299:                            // preceeding it  (eg  %2.d  or %2.-5d)
0300:
0301:                            errorBadField(interp, format[fmtIndex]);
0302:                        }
0303:                    }
0304:
0305:                    // Phase 5:
0306:                    // Setting the length modifier.
0307:
0308:                    if (format[fmtIndex] == 'h') {
0309:                        fmtIndex++;
0310:                        checkOverFlow(interp, format, fmtIndex);
0311:                        useShort = true;
0312:                    } else if (format[fmtIndex] == 'l') {
0313:                        fmtIndex++;
0314:                        checkOverFlow(interp, format, fmtIndex);
0315:
0316:                        // 'l' is ignored, but should still be processed.
0317:                    }
0318:
0319:                    if ((argIndex < 2) || (argIndex >= argv.length)) {
0320:                        errorBadIndex(interp, gotXpg);
0321:                    }
0322:
0323:                    // Phase 6:
0324:                    // Setting conversion field.
0325:                    // At this point, variables are initialized as follows:
0326:                    //
0327:                    // width               The specified field width.  This is always
0328:                    //                         non-negative.  Zero is the default.
0329:                    // precision           The specified precision.  The default
0330:                    //                         is -1.
0331:                    // argIndex            The argument index from the argv array 
0332:                    //                         for the appropriate arg.
0333:                    // fmtFlags            The format flags are set via bitwise 
0334:                    //                         operations.  Below are the bits
0335:                    //                         and their meanings.
0336:
0337:                    //     ALT_OUTPUT          set if a '#' is present.
0338:                    //     SHOW_SIGN           set if a '+' is present.
0339:                    //     SPACE_OR_SIGN       set if a ' ' is present.
0340:                    //     LEFT_JUSTIFY        set if a '-' is present or if the
0341:                    //                           field width was negative.
0342:                    //     PAD_W_ZERO          set if a '0' is present
0343:
0344:                    String strValue = "";
0345:                    char index = format[fmtIndex];
0346:
0347:                    switch (index) {
0348:                    case 'u':
0349:                    case 'd':
0350:                    case 'o':
0351:                    case 'x':
0352:                    case 'X':
0353:                    case 'i': {
0354:                        if (index == 'u') {
0355:                            // Since Java does not provide unsigned ints we need to 
0356:                            // make our own.  If the value is negative we need to 
0357:                            // clear out all of the leading bits from the 33rd bit
0358:                            // and on.  The result is a long value equal to that
0359:                            // of an unsigned int.
0360:
0361:                            lngValue = (long) TclInteger.get(interp,
0362:                                    argv[argIndex]);
0363:                            if (lngValue < 0) {
0364:                                lngValue = (lngValue << 32);
0365:                                lngValue = (lngValue >>> 32);
0366:                            }
0367:                        } else {
0368:                            fmtFlags |= SIGNED_VALUE;
0369:                            lngValue = (long) TclInteger.get(interp,
0370:                                    argv[argIndex]);
0371:                        }
0372:
0373:                        // If the useShort option has been selected, we need
0374:                        // to clear all but the first 16 bits.
0375:
0376:                        if (useShort) {
0377:                            lngValue = (lngValue << 48);
0378:                            lngValue = (lngValue >> 48);
0379:                        }
0380:
0381:                        if (index == 'o') {
0382:                            sbuf
0383:                                    .append(cvtLngToStr(lngValue, width,
0384:                                            precision, fmtFlags, 8, "01234567"
0385:                                                    .toCharArray(), "0"));
0386:                        } else if (index == 'x') {
0387:                            sbuf.append(cvtLngToStr(lngValue, width, precision,
0388:                                    fmtFlags, 16, "0123456789abcdef"
0389:                                            .toCharArray(), "0x"));
0390:                        } else if (index == 'X') {
0391:                            sbuf.append(cvtLngToStr(lngValue, width, precision,
0392:                                    fmtFlags, 16, "0123456789ABCDEF"
0393:                                            .toCharArray(), "0X"));
0394:                        } else {
0395:                            sbuf.append(cvtLngToStr(lngValue, width, precision,
0396:                                    fmtFlags, 10, "0123456789".toCharArray(),
0397:                                    ""));
0398:                        }
0399:                        break;
0400:                    }
0401:                    case 'c': {
0402:                        intValue = 0;
0403:                        char arr[] = { (char) TclInteger.get(interp,
0404:                                argv[argIndex]) };
0405:                        strValue = new String(arr);
0406:                        sbuf.append(cvtStrToStr(strValue, width, precision,
0407:                                fmtFlags));
0408:                        break;
0409:                    }
0410:                    case 's': {
0411:                        strValue = argv[argIndex].toString();
0412:                        sbuf.append(cvtStrToStr(strValue, width, precision,
0413:                                fmtFlags));
0414:                        break;
0415:                    }
0416:                    case 'f': {
0417:                        dblValue = TclDouble.get(interp, argv[argIndex]);
0418:                        sbuf.append(cvtDblToStr(dblValue, width, precision,
0419:                                fmtFlags, 10, "0123456789".toCharArray(), "",
0420:                                FLOAT));
0421:                        break;
0422:                    }
0423:                    case 'e': {
0424:                        dblValue = TclDouble.get(interp, argv[argIndex]);
0425:                        sbuf.append(cvtDblToStr(dblValue, width, precision,
0426:                                fmtFlags, 10, "e".toCharArray(), "", EXP));
0427:                        break;
0428:                    }
0429:                    case 'E': {
0430:                        dblValue = TclDouble.get(interp, argv[argIndex]);
0431:                        sbuf.append(cvtDblToStr(dblValue, width, precision,
0432:                                fmtFlags, 10, "E".toCharArray(), "", EXP));
0433:                        break;
0434:                    }
0435:                    case 'g': {
0436:                        dblValue = TclDouble.get(interp, argv[argIndex]);
0437:                        sbuf.append(cvtDblToStr(dblValue, width, precision,
0438:                                fmtFlags, 10, "e".toCharArray(), "", GENERIC));
0439:                        break;
0440:                    }
0441:                    case 'G': {
0442:                        dblValue = TclDouble.get(interp, argv[argIndex]);
0443:                        sbuf.append(cvtDblToStr(dblValue, width, precision,
0444:                                fmtFlags, 10, "E".toCharArray(), "", GENERIC));
0445:                        break;
0446:                    }
0447:                    default: {
0448:                        errorBadField(interp, format[fmtIndex]);
0449:                    }
0450:                    }
0451:                    fmtIndex++;
0452:                    argIndex++;
0453:                }
0454:                interp.setResult(sbuf.toString());
0455:            }
0456:
0457:            /**
0458:             * This procedure is invoked in "phase 6" od the Format cmdProc.  It 
0459:             * converts the lngValue to a string with a specified format determined by
0460:             * the other input variables.
0461:             * @param lngValue  - Is the value of the argument input
0462:             * @param width     - The minimum width of the string.
0463:             * @param precision - The minimum width if the integer.  If the string len 
0464:             *                        is less than precision, leading 0 are appended.
0465:             * @param flags     - Specifies various formatting to the string 
0466:             *                        representation (-, +, space, 0, #)
0467:             * @param base      - The base of the integer (8, 10, 16)
0468:             * @param charSet   - The char set to use for the conversion to ascii OR
0469:             *                        The char used for sci notation.
0470:             * @param altPrefix - If not empty, str to append on the beginnig of the 
0471:             *                        resulting string  (eg 0 or 0x or 0X ).  
0472:             * @return String representation of the long.
0473:             */
0474:
0475:            private String cvtLngToStr(long lngValue, int width, int precision,
0476:                    int flags, int base, char[] charSet, String altPrefix) {
0477:                StringBuffer sbuf = new StringBuffer(100);
0478:                StringBuffer tmpBuf = new StringBuffer(100);
0479:
0480:                int i;
0481:                int length;
0482:                int nspace;
0483:                int prefixSize = 0;
0484:                char prefix = 0;
0485:
0486:                // For the format %#x, the value zero is printed "0" not "0x0".
0487:                // I think this is stupid.
0488:
0489:                if (lngValue == 0) {
0490:                    flags = (flags | ALT_OUTPUT);
0491:                }
0492:
0493:                if ((flags & SIGNED_VALUE) != 0) {
0494:                    if (lngValue < 0) {
0495:                        if (altPrefix.length() > 0) {
0496:                            lngValue = (lngValue << 32);
0497:                            lngValue = (lngValue >>> 32);
0498:                        } else {
0499:                            lngValue = -lngValue;
0500:                            prefix = '-';
0501:                            prefixSize = 1;
0502:                        }
0503:                    } else if ((flags & SHOW_SIGN) != 0) {
0504:                        prefix = '+';
0505:                        prefixSize = 1;
0506:                    } else if ((flags & SPACE_OR_SIGN) != 0) {
0507:                        prefix = ' ';
0508:                        prefixSize = 1;
0509:                    }
0510:                }
0511:
0512:                if (((PAD_W_ZERO & flags) != 0)
0513:                        && (precision < width - prefixSize)) {
0514:                    precision = width - prefixSize;
0515:                }
0516:
0517:                // Convert to ascii
0518:
0519:                do {
0520:                    sbuf.insert(0, charSet[(int) (lngValue % base)]);
0521:                    lngValue = lngValue / base;
0522:                } while (lngValue > 0);
0523:
0524:                length = sbuf.length();
0525:                for (i = (precision - length); i > 0; i--) {
0526:                    sbuf.insert(0, '0');
0527:                }
0528:                if (prefix != 0) {
0529:                    sbuf.insert(0, prefix);
0530:                }
0531:                if ((flags & ALT_OUTPUT) != 0) {
0532:                    if ((altPrefix.length() > 0)
0533:                            && (sbuf.charAt(0) != altPrefix.charAt(0))) {
0534:                        sbuf.insert(0, altPrefix);
0535:                    }
0536:                }
0537:
0538:                // The text of the conversion is pointed to by "bufpt" and is
0539:                // "length" characters long.  The field width is "width".  Do
0540:                // the output.
0541:
0542:                nspace = width - sbuf.length();
0543:                if (nspace > 0) {
0544:                    tmpBuf.ensureCapacity(nspace);
0545:                    for (i = 0; i < nspace; i++) {
0546:                        tmpBuf.append(' ');
0547:                    }
0548:                }
0549:
0550:                if ((LEFT_JUSTIFY & flags) != 0) {
0551:                    // left justified
0552:
0553:                    sbuf.append(tmpBuf);
0554:                    return sbuf.toString();
0555:                } else {
0556:                    // right justified
0557:
0558:                    tmpBuf.append(sbuf);
0559:                    return tmpBuf.toString();
0560:                }
0561:            }
0562:
0563:            // Convert a double value to a Java String.
0564:
0565:            static String toString(double dblValue, int precision, int base) {
0566:                return cvtDblToStr(dblValue, 0, precision, 0, base, "e"
0567:                        .toCharArray(), null, GENERIC);
0568:            }
0569:
0570:            /**
0571:             * This procedure is invoked in "phase 6" od the Format cmdProc.  It 
0572:             * converts the lngValue to a string with a specified format determined 
0573:             * by the other input variables.
0574:             * @param dblValue  - Is the value of the argument input
0575:             * @param width     - The minimum width of the string.
0576:             * @param precision - The minimum width if the integer.  If the string len 
0577:             *                        is less than precision, leading 0 are appended.
0578:             * @param flags     - Specifies various formatting to the string 
0579:             *                        representation (-, +, space, 0, #)
0580:             * @param base      - The base of the integer (8, 10, 16)
0581:             * @param charSet   - The char set to use for the conversion to ascii OR
0582:             *                        The char used for sci notation.
0583:             * @param altPrefix - If not empty, str to append on the beginnig of the 
0584:             *                        resulting string  (eg 0 or 0x or 0X ).  
0585:             * @param xtype     - Either FLOAT, EXP, or GENERIC depending on the 
0586:             *                        format specifier.
0587:             * @return String representation of the long.
0588:             */
0589:
0590:            private static String cvtDblToStr(double dblValue, int width,
0591:                    int precision, int flags, int base, char[] charSet,
0592:                    String altPrefix, int xtype) {
0593:                StringBuffer sbuf = new StringBuffer(100);
0594:                int i;
0595:                int exp;
0596:                int length;
0597:                int count;
0598:                int digit;
0599:                int prefixSize = 0;
0600:                char prefix = 0;
0601:                double rounder;
0602:                boolean flag_exp = false; // Flag for exponential representation
0603:                boolean flag_rtz = true; // Flag for "remove trailing zeros"
0604:                boolean flag_dp = true; // Flag for remove "decimal point"
0605:
0606:                if (Double.isNaN(dblValue)) {
0607:                    return "NaN";
0608:                }
0609:                if (dblValue == Double.NEGATIVE_INFINITY) {
0610:                    return "-Inf";
0611:                }
0612:                if (dblValue == Double.POSITIVE_INFINITY) {
0613:                    return "Inf";
0614:                }
0615:
0616:                // If precision < 0 (eg -1) then the precision defaults
0617:
0618:                if (precision < 0) {
0619:                    precision = 6;
0620:                }
0621:
0622:                if (dblValue < 0.0) {
0623:                    dblValue = -dblValue;
0624:                    prefix = '-';
0625:                    prefixSize = 1;
0626:                } else if (dblValue == 0.0
0627:                        && (new Double(dblValue)).equals((new Double(-0.0)))) {
0628:                    // Handle -0.0
0629:                    //
0630:                    // 15.19.1 "Numerical Comparison Operators <, <=, >, and >= "
0631:                    // of the Java Language Spec says:
0632:                    // "Positive zero and negative zero are considered
0633:                    // equal. Therefore, -0.0<0.0 is false, for example, but
0634:                    // -0.0<=0.0 is true."
0635:                    //
0636:                    // The Double.equal man page says:
0637:                    // "If d1 represents +0.0 while d2 represents -0.0, or
0638:                    // vice versa, the equal test has the value false, even
0639:                    // though +0.0==-0.0 has the value true. This allows
0640:                    // hashtables to operate properly.
0641:
0642:                    dblValue = -dblValue;
0643:                    prefix = '-';
0644:                    prefixSize = 1;
0645:                } else if ((flags & SHOW_SIGN) != 0) {
0646:                    prefix = '+';
0647:                    prefixSize = 1;
0648:                } else if ((flags & SPACE_OR_SIGN) != 0) {
0649:                    prefix = ' ';
0650:                    prefixSize = 1;
0651:                }
0652:
0653:                // For GENERIC xtypes the precision includes the ones digit
0654:                // so just decrement to get the correct precision.
0655:
0656:                if (xtype == GENERIC && precision > 0) {
0657:                    precision--;
0658:                }
0659:
0660:                // Rounding works like BSD when the constant 0.4999 is used.  Wierd!
0661:
0662:                for (i = precision, rounder = 0.4999; i > 0; i--, rounder *= 0.1)
0663:                    ;
0664:
0665:                if (xtype == FLOAT) {
0666:                    dblValue += rounder;
0667:                }
0668:
0669:                // Normalize dblValue to within 10.0 > dblValue >= 1.0
0670:
0671:                exp = 0;
0672:                if (dblValue > 0.0) {
0673:                    int k = 0;
0674:                    while ((dblValue >= 1e8) && (k++ < 100)) {
0675:                        dblValue *= 1e-8;
0676:                        exp += 8;
0677:                    }
0678:                    while ((dblValue >= 10.0) && (k++ < 100)) {
0679:                        dblValue *= 0.1;
0680:                        exp++;
0681:                    }
0682:                    while ((dblValue < 1e-8) && (k++ < 100)) {
0683:                        dblValue *= 1e8;
0684:                        exp -= 8;
0685:                    }
0686:                    while ((dblValue < 1.0) && (k++ < 100)) {
0687:                        dblValue *= 10.0;
0688:                        exp--;
0689:                    }
0690:                    if (k >= 100) {
0691:                        return "NaN";
0692:                    }
0693:                }
0694:
0695:                // If the field type is GENERIC, then convert to either EXP
0696:                // or FLOAT, as appropriate.
0697:
0698:                flag_exp = xtype == EXP;
0699:                if (xtype != FLOAT) {
0700:                    dblValue += rounder;
0701:                    if (dblValue >= 10.0) {
0702:                        dblValue *= 0.1;
0703:                        exp++;
0704:                    }
0705:                }
0706:                if (xtype == GENERIC) {
0707:                    flag_rtz = !((flags & ALT_OUTPUT) != 0);
0708:                    if ((exp < -4) || (exp > precision)) {
0709:                        xtype = EXP;
0710:                    } else {
0711:                        precision = (precision - exp);
0712:                        xtype = FLOAT;
0713:                    }
0714:                } else {
0715:                    flag_rtz = false;
0716:                }
0717:
0718:                // The "exp+precision" test causes output to be of type EXP if
0719:                // the precision is too large to fit in buf[].
0720:
0721:                count = 0;
0722:                if (xtype == FLOAT) {
0723:                    flag_dp = ((precision > 0) || ((flags & ALT_OUTPUT) != 0));
0724:                    if (prefixSize > 0) {
0725:                        // Sign
0726:
0727:                        sbuf.append(prefix);
0728:                    }
0729:                    if (exp < 0) {
0730:                        // Digits before "."
0731:
0732:                        sbuf.append('0');
0733:                    }
0734:                    for (; exp >= 0; exp--) {
0735:                        if (count++ >= 16) {
0736:                            sbuf.append('0');
0737:                        } else {
0738:                            digit = (int) dblValue;
0739:                            dblValue = (dblValue - digit) * 10.0;
0740:                            sbuf.append(digit);
0741:                        }
0742:                    }
0743:                    if (flag_dp) {
0744:                        sbuf.append('.');
0745:                    }
0746:                    for (exp++; (exp < 0) && (precision > 0); precision--, exp++) {
0747:                        sbuf.append('0');
0748:                    }
0749:                    while ((precision--) > 0) {
0750:                        if (count++ >= 16) {
0751:                            sbuf.append('0');
0752:                        } else {
0753:                            digit = (int) dblValue;
0754:                            dblValue = (dblValue - digit) * 10.0;
0755:                            sbuf.append(digit);
0756:                        }
0757:                    }
0758:
0759:                    if (flag_rtz && flag_dp) {
0760:                        // Remove trailing zeros and "." 
0761:
0762:                        int len, index = 0;
0763:                        for (len = sbuf.length() - 1; (len >= 0)
0764:                                && (sbuf.charAt(len) == '0'); len--, index++) {
0765:                        }
0766:
0767:                        if ((len >= 0) && (sbuf.charAt(len) == '.')) {
0768:                            index++;
0769:                        }
0770:
0771:                        if (index > 0) {
0772:                            sbuf.setLength(sbuf.length() - index);
0773:                        }
0774:                    }
0775:                } else {
0776:                    // EXP or GENERIC
0777:
0778:                    flag_dp = ((precision > 0) || ((flags & ALT_OUTPUT) != 0));
0779:
0780:                    if (prefixSize > 0) {
0781:                        sbuf.append(prefix);
0782:                    }
0783:                    digit = (int) dblValue;
0784:                    dblValue = (dblValue - digit) * 10.0;
0785:                    sbuf.append(digit);
0786:                    if (flag_dp) {
0787:                        sbuf.append('.');
0788:                    }
0789:                    while (precision-- > 0) {
0790:                        if (count++ >= 16) {
0791:                            sbuf.append('0');
0792:                        } else {
0793:                            digit = (int) dblValue;
0794:                            dblValue = (dblValue - digit) * 10.0;
0795:                            sbuf.append(digit);
0796:                        }
0797:                    }
0798:
0799:                    if (flag_rtz && flag_dp) {
0800:                        // Remove trailing zeros and "."
0801:
0802:                        for (i = 0, length = (sbuf.length() - 1); (length >= 0)
0803:                                && (sbuf.charAt(length) == '0'); length--, i++)
0804:                            ;
0805:
0806:                        if ((length >= 0) && (sbuf.charAt(length) == '.')) {
0807:                            i++;
0808:                        }
0809:
0810:                        if (i > 0) {
0811:                            sbuf.setLength(sbuf.length() - i);
0812:                        }
0813:                    }
0814:                    if ((exp != 0) || flag_exp) {
0815:                        sbuf.append(charSet[0]);
0816:                        if (exp < 0) {
0817:                            sbuf.append('-');
0818:                            exp = -exp;
0819:                        } else {
0820:                            sbuf.append('+');
0821:                        }
0822:                        if (exp >= 100) {
0823:                            sbuf.append((exp / 100));
0824:                            exp %= 100;
0825:                        } else {
0826:                            sbuf.append('0');
0827:                        }
0828:                        sbuf.append(exp / 10);
0829:                        sbuf.append(exp % 10);
0830:                    }
0831:                }
0832:
0833:                // The converted number is in sbuf. Output it.
0834:                // Note that the number is in the usual order, not reversed as with
0835:                // integer conversions.
0836:
0837:                length = sbuf.length();
0838:
0839:                // Special case:  Add leading zeros if the PAD_W_ZERO flag is
0840:                // set and we are not left justified 
0841:
0842:                if (((PAD_W_ZERO & flags) != 0)
0843:                        && ((LEFT_JUSTIFY & flags) == 0)) {
0844:                    int nPad = width - length;
0845:                    i = prefixSize;
0846:                    while ((nPad--) > 0) {
0847:                        sbuf.insert(prefixSize, '0');
0848:                    }
0849:                    length = width;
0850:                }
0851:
0852:                // Count the number of spaces remaining and create a StringBuffer
0853:                // (tmpBuf) with the correct number of spaces.
0854:
0855:                int nspace = width - length;
0856:                StringBuffer tmpBuf = new StringBuffer(100 + nspace);
0857:                if (nspace > 0) {
0858:                    for (i = 0; i < nspace; i++) {
0859:                        tmpBuf.append(' ');
0860:                    }
0861:                }
0862:
0863:                if ((LEFT_JUSTIFY & flags) != 0) {
0864:                    // left justified
0865:
0866:                    sbuf.append(tmpBuf);
0867:                    return sbuf.toString();
0868:                } else {
0869:                    // right justified
0870:
0871:                    tmpBuf.append(sbuf);
0872:                    return tmpBuf.toString();
0873:                }
0874:            }
0875:
0876:            /**
0877:             * This procedure is invoked in "phase 6" od the Format cmdProc.  It 
0878:             * converts the strValue to a string with a specified format determined 
0879:             * by the other input variables.
0880:             * @param strValue  - Is the String w/o formatting.
0881:             * @param width     - The minimum width of the string.
0882:             * @param precision - The minimum width if the integer.  If the string 
0883:             *                        len is less than precision, leading 0 are 
0884:             *                        appended.
0885:             * @param flags     - Specifies various formatting to the string 
0886:             *                        representation (-, +, space, 0, #)
0887:             * @return String representation of the integer.
0888:             */
0889:
0890:            private static String cvtStrToStr(String strValue, int width,
0891:                    int precision, int flags) {
0892:                String left = "";
0893:                String right = "";
0894:                StringBuffer sbuf = new StringBuffer(100);
0895:
0896:                if (precision < 0) {
0897:                    precision = 0;
0898:                }
0899:
0900:                if ((precision != 0) && (precision < strValue.length())) {
0901:                    strValue = strValue.substring(0, precision);
0902:                }
0903:
0904:                if (width > strValue.length()) {
0905:                    sbuf.setLength(0);
0906:                    int index = width - strValue.length();
0907:                    for (int i = 0; i < index; i++) {
0908:                        if ((flags & PAD_W_ZERO) != 0) {
0909:                            sbuf.append('0');
0910:                        } else {
0911:                            sbuf.append(' ');
0912:                        }
0913:                    }
0914:                    if ((LEFT_JUSTIFY & flags) != 0) {
0915:                        right = sbuf.toString();
0916:                    } else {
0917:                        left = sbuf.toString();
0918:                    }
0919:                }
0920:
0921:                sbuf.setLength(0);
0922:                sbuf.append(left);
0923:                sbuf.append(strValue);
0924:                sbuf.append(right);
0925:                return sbuf.toString();
0926:            }
0927:
0928:            /**
0929:             * Search through the array while the current char is a digit.  When end 
0930:             * of array occurs or the char is not a digit, stop the loop, convert the
0931:             * sub-array into a long.  At this point update a StrtoulResult object
0932:             * that contains the new long value and the current pointer to the array.
0933:             * Returns a StrtoulResult tmp object to hold result data.
0934:             *
0935:             * @param interp - the current interpreter (can't be null)
0936:             * @param arr - the array that contains a string representation of an int.
0937:             * @param endIndex - the arr index where the numeric value begins.
0938:             */
0939:
0940:            private static StrtoulResult strtoul(Interp interp, char[] arr,
0941:                    int endIndex) {
0942:                int orgIndex;
0943:                StrtoulResult strtoulResult = interp.strtoulResult;
0944:
0945:                orgIndex = endIndex;
0946:                for (; endIndex < arr.length; endIndex++) {
0947:                    if (!Character.isDigit(arr[endIndex])) {
0948:                        break;
0949:                    }
0950:                }
0951:                long lval = Long.parseLong(new String(arr, orgIndex, endIndex
0952:                        - orgIndex));
0953:                strtoulResult.update(lval, endIndex, 0);
0954:                return strtoulResult;
0955:            }
0956:
0957:            /*
0958:             *
0959:             *  Error routines:
0960:             *
0961:             */
0962:
0963:            /**
0964:             * Called whenever the fmtIndex in the cmdProc is changed.  It verifies
0965:             * the the array index is still within the bounds of the array.  If no
0966:             * throw error.
0967:             * @param interp  - The TclInterp which called the cmdProc method .
0968:             * @param arr     - The array to be checked.
0969:             * @param index   - The new value for the array index.
0970:             */
0971:
0972:            private static void checkOverFlow(Interp interp, char[] arr,
0973:                    int index) throws TclException {
0974:                if ((index >= arr.length) || (index < 0)) {
0975:                    throw new TclException(interp,
0976:                            "\"%n$\" argument index out of range");
0977:                }
0978:            }
0979:
0980:            /**
0981:             * Called whenever Sequential format specifiers are interlaced with 
0982:             * XPG format specifiers in one call to cmdProc.
0983:             *
0984:             * @param interp  - The TclInterp which called the cmdProc method .
0985:             */
0986:
0987:            private static void errorMixedXPG(Interp interp)
0988:                    throws TclException {
0989:                throw new TclException(interp,
0990:                        "cannot mix \"%\" and \"%n$\" conversion specifiers");
0991:            }
0992:
0993:            /**
0994:             * Called whenever the argIndex access outside the argv array.  If the
0995:             * type is an XPG then the error message is different.
0996:             *
0997:             * @param interp  - The TclInterp which called the cmdProc method .
0998:             * @param gotXpg  - Boolean the determines if the current format is of a
0999:             *                      XPG type or Sequential
1000:             */
1001:
1002:            private static void errorBadIndex(Interp interp, boolean gotXpg)
1003:                    throws TclException {
1004:                if (gotXpg) {
1005:                    throw new TclException(interp,
1006:                            "\"%n$\" argument index out of range");
1007:                } else {
1008:                    throw new TclException(interp,
1009:                            "not enough arguments for all format specifiers");
1010:                }
1011:            }
1012:
1013:            /**
1014:             * Called whenever the current char in the format array is erroneous
1015:             *
1016:             * @param interp  - The TclInterp which called the cmdProc method .
1017:             * @param fieldSpecifier  - The erroneous character
1018:             */
1019:
1020:            private static void errorBadField(Interp interp, char fieldSpecifier)
1021:                    throws TclException {
1022:                throw new TclException(interp, "bad field specifier \""
1023:                        + fieldSpecifier + "\"");
1024:            }
1025:
1026:            /**
1027:             * Called whenever the a '%' is found but then the format string ends.
1028:             *
1029:             * @param interp  - The TclInterp which called the cmdProc method .
1030:             */
1031:
1032:            private static void errorEndMiddle(Interp interp)
1033:                    throws TclException {
1034:                throw new TclException(interp,
1035:                        "format string ended in middle of field specifier");
1036:            }
1037:
1038:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.