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