annotate graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/StringFormatter.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
13514
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
1 /*
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
3 * code is released under a tri EPL/GPL/LGPL license. You can use it,
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
4 * redistribute it and/or modify it under the terms of the:
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
5 *
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
6 * Eclipse Public License version 1.0
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
7 * GNU General Public License version 2
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
8 * GNU Lesser General Public License version 2.1
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
9 */
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
10 package com.oracle.truffle.ruby.runtime.core;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
11
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
12 import java.io.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
13 import java.util.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
14
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
15 import com.oracle.truffle.ruby.runtime.core.array.*;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
16
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
17 public class StringFormatter {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
18
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
19 public static String format(String format, List<Object> values) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
20 final ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
21 final PrintStream printStream = new PrintStream(byteArray);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
22
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
23 format(printStream, format, values);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
24
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
25 return byteArray.toString();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
26 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
27
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
28 public static void format(PrintStream stream, String format, List<Object> values) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
29 /*
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
30 * See http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-sprintf.
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
31 *
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
32 * At the moment we just do the basics that we need. We will need a proper lexer later on.
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
33 * Or better than that we could compile to Truffle nodes if the format string is constant! I
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
34 * don't think we can easily translate to Java's format syntax, otherwise JRuby would do
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
35 * that and they don't.
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
36 */
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
37
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
38 // I'm not using a for loop, because Checkstyle won't let me modify the control variable
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
39
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
40 int n = 0;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
41 int v = 0;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
42
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
43 while (n < format.length()) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
44 final char c = format.charAt(n);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
45 n++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
46
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
47 if (c == '%') {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
48 // %[flags][width][.precision]type
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
49
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
50 final String flagChars = "0";
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
51
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
52 boolean zeroPad = false;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
53
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
54 while (n < format.length() && flagChars.indexOf(format.charAt(n)) != -1) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
55 switch (format.charAt(n)) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
56 case '0':
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
57 zeroPad = true;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
58 break;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
59 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
60
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
61 n++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
62 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
63
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
64 int width;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
65
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
66 if (n < format.length() && Character.isDigit(format.charAt(n))) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
67 final int widthStart = n;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
68
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
69 while (Character.isDigit(format.charAt(n))) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
70 n++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
71 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
72
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
73 width = Integer.parseInt(format.substring(widthStart, n));
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
74 } else {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
75 width = 0;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
76 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
77
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
78 int precision;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
79
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
80 if (format.charAt(n) == '.') {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
81 n++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
82
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
83 final int precisionStart = n;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
84
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
85 while (Character.isDigit(format.charAt(n))) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
86 n++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
87 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
88
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
89 precision = Integer.parseInt(format.substring(precisionStart, n));
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
90 } else {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
91 precision = 5;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
92 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
93
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
94 final char type = format.charAt(n);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
95 n++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
96
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
97 final StringBuilder formatBuilder = new StringBuilder();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
98
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
99 formatBuilder.append("%");
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
100
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
101 if (width > 0) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
102 if (zeroPad) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
103 formatBuilder.append("0");
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
104 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
105
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
106 formatBuilder.append(width);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
107 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
108
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
109 switch (type) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
110 case 'd': {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
111 formatBuilder.append("d");
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
112 final int value = GeneralConversions.toFixnum(values.get(v));
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
113 stream.printf(formatBuilder.toString(), value);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
114 break;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
115 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
116
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
117 case 'f': {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
118 formatBuilder.append(".");
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
119 formatBuilder.append(precision);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
120 formatBuilder.append("f");
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
121 final double value = GeneralConversions.toFloat(values.get(v));
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
122 stream.printf(formatBuilder.toString(), value);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
123 break;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
124 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
125
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
126 default:
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
127 throw new RuntimeException("Kernel#sprintf error");
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
128 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
129
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
130 v++;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
131 } else {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
132 stream.print(c);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
133 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
134 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
135 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
136
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
137 public static void formatPuts(PrintStream stream, List<Object> args) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
138 if (args.size() > 0) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
139 formatPutsInner(stream, args);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
140 } else {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
141 stream.println();
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
142 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
143 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
144
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
145 public static void formatPutsInner(PrintStream stream, List<Object> args) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
146 if (args.size() > 0) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
147 for (Object arg : args) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
148 if (arg instanceof RubyArray) {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
149 final RubyArray array = (RubyArray) arg;
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
150 formatPutsInner(stream, array.asList());
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
151 } else {
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
152 stream.println(arg);
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
153 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
154 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
155 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
156 }
0fbee3eb71f0 Ruby: import project.
Chris Seaton <chris.seaton@oracle.com>
parents:
diff changeset
157 }