PageRenderTime 5ms CodeModel.GetById 52ms app.highlight 133ms RepoModel.GetById 22ms app.codeStats 1ms

/usr/src/cmd/cmd-inet/usr.sadm/dhcpmgr/com/sun/dhcpmgr/cli/common/Format.java

https://bitbucket.org/buffyg/illumos-gate-1514
Java | 608 lines | 387 code | 63 blank | 158 comment | 222 complexity | 9ac1d6da7d55165d2f0f9d1d14bdee44 MD5 | raw file
  1/*
  2 * CDDL HEADER START
  3 *
  4 * The contents of this file are subject to the terms of the
  5 * Common Development and Distribution License, Version 1.0 only
  6 * (the "License").  You may not use this file except in compliance
  7 * with the License.
  8 *
  9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 10 * or http://www.opensolaris.org/os/licensing.
 11 * See the License for the specific language governing permissions
 12 * and limitations under the License.
 13 *
 14 * When distributing Covered Code, include this CDDL HEADER in each
 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 16 * If applicable, add the following below this CDDL HEADER, with the
 17 * fields enclosed by brackets "[]" replaced with your own identifying
 18 * information: Portions Copyright [yyyy] [name of copyright owner]
 19 *
 20 * CDDL HEADER END
 21 */
 22/*
 23 * ident	"%Z%%M%	%I%	%E% SMI"
 24 *
 25 * Copyright (c) 2001 by Sun Microsystems, Inc.
 26 * All rights reserved.
 27 */
 28
 29/*
 30 * Cay S. Horstmann & Gary Cornell, Core Java
 31 * Published By Sun Microsystems Press/Prentice-Hall
 32 * Copyright (C) 1997 Sun Microsystems Inc.
 33 * All Rights Reserved.
 34 *
 35 * Permission to use, copy, modify, and distribute this 
 36 * software and its documentation for NON-COMMERCIAL purposes
 37 * and without fee is hereby granted provided that this 
 38 * copyright notice appears in all copies. 
 39 * 
 40 * THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR 
 41 * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER 
 42 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 43 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
 44 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS
 45 * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED 
 46 * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 
 47 * THIS SOFTWARE OR ITS DERIVATIVES.
 48 */
 49 
 50/**
 51 * A class for formatting numbers that follows printf conventions.
 52 * Also implements C-like atoi and atof functions
 53 * @version 1.01 15 Feb 1996 
 54 * @author Cay Horstmann
 55 */
 56
 57package com.sun.dhcpmgr.cli.common;
 58
 59import java.io.*;
 60
 61public class Format
 62
 63{
 64    /** 
 65     * Formats the number following printf conventions.
 66     * Main limitation: Can only handle one format parameter at a time
 67     * Use multiple Format objects to format more than one number
 68     * @param s the format string following printf conventions
 69     * The string has a prefix, a format code and a suffix. The prefix and 
 70     * suffix become part of the formatted output. The format code directs the
 71     * formatting of the (single) parameter to be formatted. The code has the
 72     * following structure
 73     * <ul>
 74     * <li> a % (required)
 75     * <li> a modifier (optional)
 76     * <dl>
 77     * <dt> + <dd> forces display of + for positive numbers
 78     * <dt> 0 <dd> show leading zeroes
 79     * <dt> - <dd> align left in the field
 80     * <dt> space <dd> prepend a space in front of positive numbers
 81     * <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal
 82     * numbers. Don't suppress trailing zeroes in general floating point format.
 83     * </dl>
 84     * <li> an integer denoting field width (optional)
 85     * <li> a period followed by an integer denoting precision (optional)
 86     * <li> a format descriptor (required)
 87     * <dl>
 88     * <dt>f <dd> floating point number in fixed format
 89     * <dt>e, E <dd> floating point number in exponential notation (scientific 
 90     * format). The E format results in an uppercase E for the exponent
 91     * (1.14130E+003), the e format in a lowercase e.
 92     * <dt>g, G <dd> floating point number in general format (fixed format for
 93     * small numbers, exponential format for large numbers). Trailing zeroes
 94     * are suppressed. The G format results in an uppercase E for the exponent
 95     * (if any), the g format in a lowercase e.
 96     * <dt>d, i <dd> integer in decimal
 97     * <dt>x <dd> integer in hexadecimal
 98     * <dt>o <dd> integer in octal
 99     * <dt>s <dd> string
100     * <dt>c <dd> character
101     * </dl>
102     * </ul>
103     * @exception IllegalArgumentException if bad format
104     */
105    public Format(String s) {
106	width = 0;
107	precision = -1;
108	pre = "";
109	post = "";
110	leading_zeroes = false;
111	show_plus = false;
112	alternate = false;
113	show_space = false;
114	left_align = false;
115	fmt = ' '; 
116
117	int state = 0; 
118	int length = s.length();
119	int parse_state = 0; 
120	// 0 = prefix, 1 = flags, 2 = width, 3 = precision,
121	// 4 = format, 5 = end
122	int i = 0;
123
124	while (parse_state == 0) {
125	    if (i >= length) {
126		parse_state = 5;
127	    } else if (s.charAt(i) == '%') {
128		if (i < length - 1) {
129		    if (s.charAt(i + 1) == '%') {
130			pre = pre + '%';
131			i++;
132		    } else {
133			parse_state = 1;
134		    }
135	 	} else {
136		    throw new java.lang.IllegalArgumentException();
137		}
138	    } else {
139		pre = pre + s.charAt(i);
140	    }
141	    i++;
142	}
143
144	while (parse_state == 1) {
145	    if (i >= length) {
146	        parse_state = 5;
147	    } else if (s.charAt(i) == ' ') {
148		show_space = true;
149	    } else if (s.charAt(i) == '-') {
150		left_align = true; 
151	    } else if (s.charAt(i) == '+') {
152		show_plus = true;
153	    } else if (s.charAt(i) == '0') {
154		leading_zeroes = true;
155	    } else if (s.charAt(i) == '#') {
156		alternate = true;
157	    } else {
158		parse_state = 2; i--;
159	    }
160	    i++;
161	}
162
163	while (parse_state == 2) {
164	    if (i >= length) {
165		parse_state = 5;
166	    } else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {
167		width = width * 10 + s.charAt(i) - '0';
168		i++;
169	    } else if (s.charAt(i) == '.') {
170		parse_state = 3;
171		precision = 0;
172		i++;
173	    } else {
174		parse_state = 4;            
175	    }
176	}
177
178	while (parse_state == 3) {
179	    if (i >= length) {
180		parse_state = 5;
181	    } else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {
182		precision = precision * 10 + s.charAt(i) - '0';
183		i++;
184	    } else {
185		parse_state = 4;                  
186	    }
187	}
188
189	if (parse_state == 4) {
190	    if (i >= length) {
191		parse_state = 5;
192	    } else {
193		fmt = s.charAt(i);
194	    }
195	    i++;
196	}
197
198	if (i < length) {
199	    post = s.substring(i, length);
200	}      
201    }      
202
203    /** 
204     * prints a formatted number following printf conventions
205     * @param s a PrintStream
206     * @param fmt the format string
207     * @param x the double to print
208     */
209    public static void print(java.io.PrintStream s, String fmt, double x) {
210	s.print(new Format(fmt).form(x));
211    }
212
213    /** 
214     * prints a formatted number following printf conventions
215     * @param s a PrintStream
216     * @param fmt the format string
217     * @param x the long to print
218     */
219    public static void print(java.io.PrintStream s, String fmt, long x) {
220	s.print(new Format(fmt).form(x));
221    }
222
223    /** 
224     * prints a formatted number following printf conventions
225     * @param s a PrintStream
226     * @param fmt the format string
227     * @param x the character to 
228     */
229    public static void print(java.io.PrintStream s, String fmt, char x) {
230	s.print(new Format(fmt).form(x));
231    }
232
233    /** 
234     * prints a formatted number following printf conventions
235     * @param s a PrintStream, fmt the format string
236     * @param x a string that represents the digits to print
237     */
238    public static void print(java.io.PrintStream s, String fmt, String x) {
239	s.print(new Format(fmt).form(x));
240    }
241   
242    /** 
243     * Converts a string of digits(decimal, octal or hex) to an integer
244     * @param s a string
245     * @return the numeric value of the prefix of s representing a base
246     * 10 integer
247     */
248    public static int atoi(String s) {
249	return (int)atol(s);
250    } 
251   
252    /** 
253     * Converts a string of digits(decimal, octal or hex) to a long integer
254     * @param s a string
255     * @return the numeric value of the prefix of s representing a base
256     * 10 integer
257     */
258    public static long atol(String s) {
259	int i = 0;
260
261	while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
262	    i++;
263	}
264
265	if (i < s.length() && s.charAt(i) == '0') {
266	    if (i + 1 < s.length() && (s.charAt(i + 1) == 'x' ||
267		s.charAt(i + 1) == 'X')) {
268		return parseLong(s.substring(i + 2), 16);
269	    } else {
270		return parseLong(s, 8);
271	    }
272	} else {
273	    return parseLong(s, 10);
274	}
275    }
276
277    private static long parseLong(String s, int base) {
278	int i = 0;
279	int sign = 1;
280	long r = 0;
281      
282	while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
283	    i++;
284	}
285
286	if (i < s.length() && s.charAt(i) == '-') {
287	    sign = -1; i++;
288	} else if (i < s.length() && s.charAt(i) == '+') {
289	    i++;
290	}
291
292	while (i < s.length()) {
293	    char ch = s.charAt(i);
294	    if ('0' <= ch && ch < '0' + base) {
295		r = r * base + ch - '0';
296	    } else if ('A' <= ch && ch < 'A' + base - 10) {
297		r = r * base + ch - 'A' + 10;
298	    } else if ('a' <= ch && ch < 'a' + base - 10) {
299		r = r * base + ch - 'a' + 10;
300	    } else {
301		return r * sign;
302	    }
303	    i++;
304	}
305	return r * sign;      
306    }
307      
308    /** 
309    * Converts a string of digits to an double
310    * @param s a string
311    */
312    public static double atof(String s) {
313	int i = 0;
314	int sign = 1;
315	double r = 0; // integer part
316	double f = 0; // fractional part
317	double p = 1; // exponent of fractional part
318	int state = 0; // 0 = int part, 1 = frac part
319      
320	while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
321	    i++;
322	}
323
324	if (i < s.length() && s.charAt(i) == '-') {
325	    sign = -1; i++;
326	} else if (i < s.length() && s.charAt(i) == '+') {
327	    i++;
328	}
329
330	while (i < s.length()) {
331	    char ch = s.charAt(i);
332	    if ('0' <= ch && ch <= '9') {
333		if (state == 0) {
334		    r = r * 10 + ch - '0';
335		} else if (state == 1) {
336		    p = p / 10;
337		    r = r + p * (ch - '0');
338		}
339	    } else if (ch == '.') {
340		if (state == 0) {
341		    state = 1; 
342		} else {
343		    return sign * r;
344		}
345	    } else if (ch == 'e' || ch == 'E') {
346		long e = (int)parseLong(s.substring(i + 1), 10);
347		return sign * r * Math.pow(10, e);
348	    } else {
349		return sign * r;
350	    }
351	    i++;
352	}
353	return sign * r;
354    }
355            
356    /** 
357     * Formats a double into a string (like sprintf in C)
358     * @param x the number to format
359     * @return the formatted string 
360     * @exception IllegalArgumentException if bad argument
361     */
362    public String form(double x) {
363	String r;
364	if (precision < 0) {
365	    precision = 6;
366	}
367
368	int s = 1;
369	if (x < 0) {
370	    x = -x;
371	    s = -1;
372	}
373
374	if (fmt == 'f') {
375	    r = fixed_format(x);
376	} else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G') {
377	    r = exp_format(x);
378	} else {
379	    throw new java.lang.IllegalArgumentException();
380	}
381      
382	return pad(sign(s, r));
383    }
384   
385    /** 
386     * Formats a long integer into a string (like sprintf in C)
387     * @param x the number to format
388     * @return the formatted string 
389     */
390    public String form(long x) {
391	String r; 
392	int s = 0;
393	if (fmt == 'd' || fmt == 'i') {
394	    s = 1;
395	    if (x < 0) {
396		x = -x; s = -1;
397	    }
398	    r = "" + x;
399	} else if (fmt == 'o') {
400	    r = convert(x, 3, 7, "01234567");
401	} else if (fmt == 'x') {
402	    r = convert(x, 4, 15, "0123456789abcdef");
403	} else if (fmt == 'X') {
404	    r = convert(x, 4, 15, "0123456789ABCDEF");
405	} else {
406	    throw new java.lang.IllegalArgumentException();
407	}         
408	return pad(sign(s, r));
409    }
410   
411    /** 
412     * Formats a character into a string (like sprintf in C)
413     * @param x the value to format
414     * @return the formatted string 
415     */
416    public String form(char c) {
417	if (fmt != 'c') {
418	    throw new java.lang.IllegalArgumentException();
419	}
420	String r = "" + c;
421	return pad(r);
422    }
423   
424    /** 
425     * Formats a string into a larger string (like sprintf in C)
426     * @param x the value to format
427     * @return the formatted string 
428     */
429    public String form(String s) {
430	if (fmt != 's') {
431	    throw new java.lang.IllegalArgumentException();
432	}
433
434	if (precision >= 0) {
435	    s = s.substring(0, precision);
436	}
437	return pad(s);
438    }
439   
440    private static String repeat(char c, int n) {
441	if (n <= 0) {
442	    return "";
443	}
444	StringBuffer s = new StringBuffer(n);
445	for (int i = 0; i < n; i++) {
446	    s.append(c);
447	}
448	return s.toString();
449    }
450
451    private static String convert(long x, int n, int m, String d) {
452	if (x == 0) {
453	    return "0";
454	}
455	String r = "";
456	while (x != 0) {
457	    r = d.charAt((int)(x & m)) + r;
458	    x = x >>> n;
459	}
460	return r;
461    }
462
463    private String pad(String r) {
464	String p = repeat(' ', width - r.length());
465	if (left_align) {
466	    return pre + r + p + post;
467	} else {
468	    return pre + p + r + post;
469	}
470    }
471   
472    private String sign(int s, String r) {
473	String p = "";
474	if (s < 0) {
475	    p = "-"; 
476	} else if (s > 0) {
477	    if (show_plus) {
478		p = "+";
479	    } else if (show_space) {
480		p = " ";
481	    }
482	} else {
483	    if (fmt == 'o' && alternate && r.length() > 0 &&
484		r.charAt(0) != '0') {
485		p = "0";
486	    } else if (fmt == 'x' && alternate) {
487		p = "0x";
488	    } else if (fmt == 'X' && alternate) {
489		p = "0X";
490	    }
491	}
492
493	int w = 0;
494	if (leading_zeroes) {
495	    w = width;
496	} else if ((fmt == 'd' || fmt == 'i' || fmt == 'x' || 
497	    fmt == 'X' || fmt == 'o') && precision > 0) {
498	    w = precision;
499	}
500      
501	return p + repeat('0', w - p.length() - r.length()) + r;
502    }
503   
504           
505    private String fixed_format(double d) {
506	String f = "";
507
508	if (d > 0x7FFFFFFFFFFFFFFFL) {
509	    return exp_format(d);
510	}
511   
512	long l = (long)(precision == 0 ? d + 0.5 : d);
513	f = f + l;
514      
515	double fr = d - l; // fractional part
516	if (fr >= 1 || fr < 0) {
517	    return exp_format(d);
518	}
519    
520	return f + frac_part(fr);
521    }   
522   
523    private String frac_part(double fr) {
524	// precondition: 0 <= fr < 1
525	String z = "";
526	if (precision > 0) {
527	    double factor = 1;
528	    String leading_zeroes = "";
529	    for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL;
530		i++) {
531		factor *= 10; 
532		leading_zeroes = leading_zeroes + "0"; 
533	    }
534	    long l = (long) (factor * fr + 0.5);
535
536	    z = leading_zeroes + l;
537	    z = z.substring(z.length() - precision, z.length());
538	}
539
540      
541	if (precision > 0 || alternate) {
542	    z = "." + z;
543	}
544
545	if ((fmt == 'G' || fmt == 'g') && !alternate) {
546	    // remove trailing zeroes and decimal point
547	    int t = z.length() - 1;
548	    while (t >= 0 && z.charAt(t) == '0') {
549		t--;
550	    }
551	    if (t >= 0 && z.charAt(t) == '.') {
552		t--;
553	    }
554	    z = z.substring(0, t + 1);
555	}
556	return z;
557    }
558
559    private String exp_format(double d) {
560	String f = "";
561	int e = 0;
562	double dd = d;
563	double factor = 1;
564
565	while (dd > 10) {
566	    e++; factor /= 10; dd = dd / 10;
567	}
568
569	while (dd < 1) {
570	    e--; factor *= 10; dd = dd * 10;
571	}
572
573	if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision) {
574	    return fixed_format(d);
575	}
576      
577	d = d * factor;
578	f = f + fixed_format(d);
579      
580	if (fmt == 'e' || fmt == 'g') {
581	    f = f + "e";
582	} else {
583	    f = f + "E";
584	}
585
586	String p = "000";      
587	if (e >= 0)  {
588	    f = f + "+";
589	    p = p + e;
590	} else {
591	    f = f + "-";
592	    p = p + (-e);
593	}
594         
595	return f + p.substring(p.length() - 3, p.length());
596    }
597   
598    private int width;
599    private int precision;
600    private String pre;
601    private String post;
602    private boolean leading_zeroes;
603    private boolean show_plus;
604    private boolean alternate;
605    private boolean show_space;
606    private boolean left_align;
607    private char fmt; // one of cdeEfgGiosxXos
608}