blob: 7ae1ccc3d954f9272acb9c6444490945dfd5ef68 [file] [log] [blame]
/*
* Copyright 2003-2004 The Apache Software Foundation.
// (c) Copyright IBM Corp. 2004, 2005 All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.axis.tools.common;
import java.util.*;
/**
* Static utility methods. Some of these methods are similar to the methods on
* java.lang.String except they are aware of C/C++ comments and string literals.
*
* TODO: Many of these methods would perform better using StringBuffer not String
*/
public final class Utils {
// All the C primitive data types
public final static Set cPrimitives =
new HashSet( Arrays.asList( new Object[] {
"void", "byte", "char", "unsigned", "signed", "int", "short",
"long", "double", "float", "struct", "class", "enum", "union" }));
// All the qualifiers that can affect C types
public final static Set cTypeQualifiers =
new HashSet(
Arrays.asList(
new Object[] { "(", ")", "*", ",", "&", "]", "[", "const" }));
public final static String whitespace = " \t\r\n";
/**
* Never instantiate this class
*/
private Utils() {
}
/**
* Is this string all whitespace?
*/
static boolean isSpace(String s) {
for (int i = 0; i < s.length(); i++)
if (!Character.isWhitespace(s.charAt(i)))
return false;
return true;
}
// TODO look for other trailing chars like { (because of class{)
static boolean startsWith(String source, String target) {
if (source == null || target == null)
return false;
if (!source.startsWith(target))
return false;
if (source.length() == target.length())
return true;
if (Character.isWhitespace(source.charAt(target.length())))
return true;
return false;
}
/**
* Performs a C-aware version of String.indexOf(char) in
* that it skips characters in string literals and comments.
*/
static int indexOf(String s, char c) throws ParsingException {
if ('"' == c)
rude("Utils.indexOf cannot be passed quotes");
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c)
return i;
i = skip(s.substring(i), i);
if (-1 == i)
return -1;
}
return -1;
}
/**
* Performs a C-aware version of String.indexOf(String) in
* that it skips characters in string literals and comments and makes
* sure that the target string is not embedded in a longer word.
*/
static int indexOf(String s, String t) {
char t0 = t.charAt(0);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == t0
&& s.substring(i).startsWith(t)
&& (0 == i || !Character.isLetterOrDigit(s.charAt(i - 1)))
&& (s.length() == (i + t.length())
|| !Character.isLetterOrDigit(s.charAt(i + t.length()))))
return i;
i = skip(s.substring(i), i);
if (-1 == i)
return -1;
}
return -1;
}
/**
* Matches braces or quotes and is C-aware.
* It skips characters in string literals and comments.
*/
static int findMatching(String s, char c1, char c2) {
int depth = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c1)
depth++;
else if (s.charAt(i) == c2) {
depth--;
if (depth == 0)
return i;
} else {
i = skip(s.substring(i), i);
if (-1 == i)
return -1;
}
}
return -1;
}
/**
* Failed to parse the source code for some reason. This method
* prints out a suitably rude message, and then what? I haven't
* quite decided yet.
*
* TODO: Do something sensible here like throw an Exception which
* will give up on this file completely and tidy up the output file.
* It may be just too dangerous to try to carry on. But we need to
* fail in such a way that the build system knows that we've failed
* for this file and can build this file without trace.
*/
public static void rude(
String reason,
String filename,
int lineno,
String codefragment)
throws ParsingException {
String text = "Bad C++ code!! ";
if (reason != null)
text += reason;
if (filename != null)
text += " " + filename + " lineno=" + lineno;
if (codefragment != null)
text += " <" + codefragment + ">";
System.err.println(text);
throw new ParsingException();
}
/**
* @see Utils.rude(String,String,int,String)
*/
public static void rude(String reason) throws ParsingException {
rude(reason, null, 0, null);
}
/**
* Escapes special characters like " so that they can be output
* in a C string literal. Also removes newlines, since C string
* literals can't be split over lines.
*/
String pretty(String s) {
StringBuffer sb = new StringBuffer(s);
for (int i = 0; i < sb.length(); i++)
switch (sb.charAt(i)) {
case '"' :
sb = sb.insert(i, '\\');
i++;
break;
case '\n' :
sb = sb.deleteCharAt(i);
i--;
break;
}
return sb.toString();
}
private static boolean startsWithComment(String s) {
if (null == s || s.length() < 2)
return false;
if (s.startsWith("//"))
return true;
if (s.startsWith("/*"))
return true;
return false;
}
private static int endOfComment(String s) {
int idx;
if (s.startsWith("//"))
idx = s.indexOf("\n");
else {
idx = s.indexOf("*/");
if (-1 != idx)
idx++; // Step over */
}
return idx;
}
private static boolean startsWithStringLiteral(String s) {
if (null == s || s.length() < 1)
return false;
if (s.startsWith("\"") || s.startsWith("'"))
return true;
return false;
}
private static int endOfStringLiteral(String s) {
boolean escape = false;
char c0 = s.charAt(0);
for (int i = 1; i < s.length(); i++) {
if (!escape && s.charAt(i) == c0)
return i;
// \" or \' does not end the literal
if ('\\' == s.charAt(i))
// Escaping a \ should switch escape off so \\' does end
// the literal
escape = !escape;
else
escape = false;
}
return -1;
}
/**
* If the String s starts with a string literal or a comment, return
* i plus the index of the end of the literal or comment. String literals
* are enclosed in " or ' and comments start with /* or //.
*/
private static int skip(String s, int i) {
int j = 0;
if (startsWithStringLiteral(s)) {
j = endOfStringLiteral(s);
if (-1 == j)
return -1;
} else if (startsWithComment(s)) {
j = endOfComment(s);
if (-1 == j)
return -1;
}
return i + j;
}
/**
* A better method than .equals() because it doesn't
* NullPointerException when one of the parameters is null.
*/
public static boolean safeEquals(Object o1, Object o2) {
if (null == o1 && null == o2)
return true;
if (null == o1 && null != o2)
return false;
if (null != o1 && null == o2)
return false;
return o1.equals(o2);
}
public static void outputDebugString(String line) {
if (!Options.quiet()) {
if (Options.verbose())
System.out.println();
System.out.println(line);
}
}
}