// ********************************************************************** // // Copyright (c) 2002 // Mutable Realms, Inc. // Huntsville, AL, USA // // All Rights Reserved // // ********************************************************************** package IceInternal; public final class StringUtil { // // Return the index of the first character in str to // appear in match, starting from 0. Returns -1 if none is // found. // public static int findFirstOf(String str, String match) { return findFirstOf(str, match, 0); } // // Return the index of the first character in str to // appear in match, starting from start. Returns -1 if none is // found. // public static int findFirstOf(String str, String match, int start) { final int len = str.length(); for(int i = start; i < len; i++) { char ch = str.charAt(i); if(match.indexOf(ch) != -1) { return i; } } return -1; } // // Return the index of the first character in str which does // not appear in match, starting from 0. Returns -1 if none is // found. // public static int findFirstNotOf(String str, String match) { return findFirstNotOf(str, match, 0); } // // Return the index of the first character in str which does // not appear in match, starting from start. Returns -1 if none is // found. // public static int findFirstNotOf(String str, String match, int start) { final int len = str.length(); for(int i = start; i < len; i++) { char ch = str.charAt(i); if(match.indexOf(ch) == -1) { return i; } } return -1; } private static void encodeChar(byte b, StringBuffer s, String special) { switch(b) { case (byte)'\\': { s.append("\\\\"); break; } case (byte)'\'': { s.append("\\'"); break; } case (byte)'"': { s.append("\\\""); break; } case (byte)'\b': { s.append("\\b"); break; } case (byte)'\f': { s.append("\\f"); break; } case (byte)'\n': { s.append("\\n"); break; } case (byte)'\r': { s.append("\\r"); break; } case (byte)'\t': { s.append("\\t"); break; } default: { if(b <= (byte)31 || b == (byte)127) // Bytes are signed in Java (-128 to 127) { s.append('\\'); String octal = Integer.toOctalString(b); // // Add leading zeroes so that we avoid problems during // decoding. For example, consider the encoded string // \0013 (i.e., a character with value 1 followed by // the character '3'). If the leading zeroes were omitted, // the result would be incorrectly interpreted by the // decoder as a single character with value 11. // for(int j = octal.length(); j < 3; j++) { s.append('0'); } s.append(octal); } else if(special != null && special.indexOf((char)b) != -1) { s.append('\\'); encodeChar(b, s, null); } else { s.append((char)b); } } } } // // Encodes a string into UTF8, escaping all characters outside the range [32-126] // as well as any special characters determined by the caller. // public static String encodeString(String s, String special) { byte[] bytes = null; try { bytes = s.getBytes("UTF8"); } catch(java.io.UnsupportedEncodingException ex) { assert(false); return null; } StringBuffer result = new StringBuffer(bytes.length); for(int i = 0; i < bytes.length; i++) { encodeChar(bytes[i], result, special); } return result.toString(); } // // Decodes a UTF8 string. Decoding starts at the given start position // (inclusive) and stops at the given end position (exclusive). If the end // position is zero, then the remainder of the string is used. Upon success, // the result parameter holds the decoded string and true is returned. // A return value of false indicates an error was detected in the encoding. // public static boolean decodeString(String s, int start, int end, Ice.StringHolder result) { final int len = s.length(); if(end == 0) { end = len; } assert(start >= 0); assert(end <= len); assert(start <= end); byte[] bytes = new byte[len]; int bc = 0; while(start < end) { char ch = s.charAt(start); if(ch == '\\') { start++; if(start == end) { return false; // Missing character } ch = s.charAt(start); switch(ch) { case '\\': { bytes[bc++] = (byte)'\\'; break; } case '\'': case '"': { bytes[bc++] = (byte)ch; break; } case 'b': { bytes[bc++] = (byte)'\b'; break; } case 'f': { bytes[bc++] = (byte)'\f'; break; } case 'n': { bytes[bc++] = (byte)'\n'; break; } case 'r': { bytes[bc++] = (byte)'\r'; break; } case 't': { bytes[bc++] = (byte)'\t'; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int count = 0; int val = 0; while(count < 3 && start < end && s.charAt(start) >= '0' && s.charAt(start) <= '9') { val <<= 3; val |= s.charAt(start) - '0'; start++; count++; } if(val > 255) { return false; // Octal value out of range } bytes[bc++] = (byte)val; continue; // don't increment start } default: { byte b = (byte)ch; if(b <= (byte)31 || b == (byte)127) // Bytes are signed in Java (-128 to 127) { return false; // Malformed encoding } else { bytes[bc++] = b; } } } } else { bytes[bc++] = (byte)ch; } start++; } try { result.value = new String(bytes, 0, bc, "UTF8"); } catch(java.io.UnsupportedEncodingException ex) { assert(false); } return true; } public static int checkQuote(String s) { return checkQuote(s, 0); } // // If a single or double quotation mark is found at the start position, // then the position of the matching closing quote is returned. If no // quotation mark is found at the start position, then 0 is returned. // If no matching closing quote is found, then -1 is returned. // public static int checkQuote(String s, int start) { char quoteChar = s.charAt(start); if(quoteChar == '"' || quoteChar == '\'') { start++; final int len = s.length(); int pos; while(start < len && (pos = s.indexOf(quoteChar, start)) != -1) { if(s.charAt(pos - 1) != '\\') { return pos; } start = pos + 1; } return -1; // Unmatched quote } return 0; // Not quoted } }