Coverage Report - org.apache.myfaces.shared_impl.util.StringUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
StringUtils
0%
0/201
0%
0/178
6.211
 
 1  
 /*
 2  
  *  Licensed to the Apache Software Foundation (ASF) under one
 3  
  *  or more contributor license agreements.  See the NOTICE file
 4  
  *  distributed with this work for additional information
 5  
  *  regarding copyright ownership.  The ASF licenses this file
 6  
  *  to you under the Apache License, Version 2.0 (the
 7  
  *  "License"); you may not use this file except in compliance
 8  
  *  with the License.  You may obtain a copy of the License at
 9  
  * 
 10  
  *  http://www.apache.org/licenses/LICENSE-2.0
 11  
  * 
 12  
  *  Unless required by applicable law or agreed to in writing,
 13  
  *  software distributed under the License is distributed on an
 14  
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  *  KIND, either express or implied.  See the License for the
 16  
  *  specific language governing permissions and limitations
 17  
  *  under the License.
 18  
  */
 19  
 package org.apache.myfaces.shared_impl.util;
 20  
 
 21  
 import org.apache.myfaces.shared_impl.util.ArrayUtils;
 22  
 
 23  
 import java.util.ArrayList;
 24  
 
 25  
 
 26  
 /**
 27  
  * Implements utility functions for the String class
 28  
  *
 29  
  * <p>
 30  
  * Emphasis on performance and reduced memory allocation/garbage collection
 31  
  * in exchange for longer more complex code.
 32  
  * </p>
 33  
  *
 34  
  * @author Anton Koinov (latest modification by $Author: skitching $)
 35  
  * @version $Revision: 673827 $ $Date: 2008-07-03 16:46:23 -0500 (Thu, 03 Jul 2008) $
 36  
  */
 37  
 public final class StringUtils
 38  
 {
 39  
     private StringUtils()
 40  0
     {
 41  
         // utility class, no instantiation
 42  0
     }
 43  
 
 44  
     //~ Methods ------------------------------------------------------------------------------------
 45  
 
 46  
     /**
 47  
      * Checks that the string represents a floating point number that CANNOT be
 48  
      * in exponential notation
 49  
      *
 50  
      * @param str the string to check
 51  
      *
 52  
      * @return boolean
 53  
      */
 54  
     public static boolean isFloatNoExponent(String str)
 55  
     {
 56  0
         int len = str.length();
 57  0
         if (len == 0)
 58  
         {
 59  0
             return false;
 60  
         }
 61  
 
 62  
         // skip first char if sign char
 63  0
         char c = str.charAt(0);
 64  0
         int  i = ((c == '-') || (c == '+')) ? 1 : 0;
 65  
 
 66  
         // is it only a sign?
 67  0
         if (i >= len)
 68  
         {
 69  0
             return false;
 70  
         }
 71  
 
 72  0
         boolean decimalPointFound = false;
 73  
 
 74  
         do
 75  
         {
 76  0
             c = str.charAt(i);
 77  0
             if (c == '.')
 78  
             {
 79  
                 // is this a second dot?
 80  0
                 if (decimalPointFound)
 81  
                 {
 82  0
                     return false;
 83  
                 }
 84  
 
 85  0
                 decimalPointFound = true;
 86  
             }
 87  0
             else if (!Character.isDigit(c))
 88  
             {
 89  0
                 return false;
 90  
             }
 91  
 
 92  0
             i++;
 93  
         }
 94  0
         while (i < len);
 95  
 
 96  0
         return true;
 97  
     }
 98  
 
 99  
     public static boolean isFloatWithOptionalExponent(String str)
 100  
     {
 101  0
         int len = str.length();
 102  0
         if (len == 0)
 103  
         {
 104  0
             return false;
 105  
         }
 106  
 
 107  
         // skip first char if sign char
 108  0
         char c = str.charAt(0);
 109  0
         int  i = ((c == '-') || (c == '+')) ? 1 : 0;
 110  
 
 111  
         // is it only a sign?
 112  0
         if (i >= len)
 113  
         {
 114  0
             return false;
 115  
         }
 116  
 
 117  0
         boolean exponentFound     = false;
 118  0
         boolean decimalPointFound = false;
 119  
 
 120  
         do
 121  
         {
 122  0
             c = str.charAt(i);
 123  0
             switch (c)
 124  
             {
 125  
                 case '.':
 126  
 
 127  
                     // is this a second one, are we in the exponent?
 128  0
                     if (decimalPointFound || exponentFound)
 129  
                     {
 130  0
                         return false;
 131  
                     }
 132  0
                     decimalPointFound = true;
 133  
 
 134  0
                     break;
 135  
 
 136  
                 case 'e':
 137  
                 case 'E':
 138  
 
 139  
                     // is this a second one?
 140  0
                     if (exponentFound)
 141  
                     {
 142  0
                         return false;
 143  
                     }
 144  0
                     exponentFound = true;
 145  
 
 146  
                     // check for exponent sign
 147  0
                     c = str.charAt(i + 1);
 148  
 
 149  0
                     if ((c == '-') || (c == '+'))
 150  
                     {
 151  0
                         i++;
 152  
                     }
 153  
 
 154  
                     break;
 155  
 
 156  
                 default:
 157  0
                     if (!Character.isDigit(c))
 158  
                     {
 159  0
                         return false;
 160  
                     }
 161  
             }
 162  
 
 163  0
             i++;
 164  
         }
 165  0
         while (i < len);
 166  
 
 167  0
         return true;
 168  
     }
 169  
 
 170  
     public static boolean isInteger(String str)
 171  
     {
 172  0
         int len = str.length();
 173  0
         if (len == 0)
 174  
         {
 175  0
             return false;
 176  
         }
 177  
 
 178  
         // skip first char if sign char
 179  0
         char c = str.charAt(0);
 180  0
         int  i = ((c == '-') || (c == '+')) ? 1 : 0;
 181  
 
 182  
         // is it only a sign?
 183  0
         if (i >= len)
 184  
         {
 185  0
             return false;
 186  
         }
 187  
 
 188  
         do
 189  
         {
 190  0
             if (!Character.isDigit(str.charAt(i)))
 191  
             {
 192  0
                 return false;
 193  
             }
 194  0
             i++;
 195  
         }
 196  0
         while (i < len);
 197  
 
 198  0
         return true;
 199  
     }
 200  
 
 201  
     public static boolean isUnsignedInteger(String str)
 202  
     {
 203  0
         int len = str.length();
 204  0
         if (len == 0)
 205  
         {
 206  0
             return false;
 207  
         }
 208  
 
 209  0
         for (int i = 0; i < len; i++)
 210  
         {
 211  0
             if (!Character.isDigit(str.charAt(i)))
 212  
             {
 213  0
                 return false;
 214  
             }
 215  
         }
 216  
 
 217  0
         return true;
 218  
     }
 219  
 
 220  
     /**
 221  
      * Undoubles the quotes inside the string <br> Example:<br>
 222  
      * <pre>
 223  
      * hello""world becomes hello"world
 224  
      * </pre>
 225  
      *
 226  
      * @param str input string to dequote
 227  
      * @param quote the quoting char
 228  
      *
 229  
      * @return dequoted string
 230  
      */
 231  
     public static String dequote(String str, char quote)
 232  
     {
 233  
         // Is there anything to dequote?
 234  0
         if (str == null)
 235  
         {
 236  0
             return null;
 237  
         }
 238  
 
 239  0
         return dequote(str, 0, str.length(), quote);
 240  
     }
 241  
 
 242  
     /**
 243  
      * Undoubles the quotes inside a substring <br> Example:<br>
 244  
      * <pre>
 245  
      * hello""world becomes hello"world
 246  
      * </pre>
 247  
      * WARNING: scan for quote may continue to the end of the string, make sure
 248  
      * that either <code>charAt(end + 1) == quote</code> or <code>end =
 249  
      * str.lentgth()</code>. If in doubt call
 250  
      * <code>dequote(str.substring(begin, end), quote)</code>
 251  
      *
 252  
      * @param str input string from which to get the substring, must not be
 253  
      *        null
 254  
      * @param begin begin index for substring
 255  
      * @param end end index for substring
 256  
      * @param quote the quoting char
 257  
      *
 258  
      * @return dequoted string
 259  
      *
 260  
      * @throws IllegalArgumentException if string is incorrectly quoted
 261  
      */
 262  
     public static String dequote(String str, int begin, int end, char quote)
 263  
     {
 264  
         // Is there anything to dequote?
 265  0
         if (begin == end)
 266  
         {
 267  0
             return "";
 268  
         }
 269  
 
 270  0
         int end_ = str.indexOf(quote, begin);
 271  
 
 272  
         // If no quotes, return the original string
 273  
         // and save StringBuffer allocation/char copying
 274  0
         if (end_ < 0)
 275  
         {
 276  0
             return str.substring(begin, end);
 277  
         }
 278  
 
 279  0
         StringBuffer sb     = new StringBuffer(end - begin);
 280  0
         int          begin_ = begin; // need begin later
 281  0
         for (; (end_ >= 0) && (end_ < end);
 282  0
             end_ = str.indexOf(quote, begin_ = end_ + 2))
 283  
         {
 284  0
             if (((end_ + 1) >= end) || (str.charAt(end_ + 1) != quote))
 285  
             {
 286  0
                 throw new IllegalArgumentException(
 287  
                     "Internal quote not doubled in string '"
 288  
                     + str.substring(begin, end) + "'");
 289  
             }
 290  
 
 291  0
             sb.append(substring(str, begin_, end_)).append(quote);
 292  
         }
 293  
 
 294  0
         return sb.append(substring(str, begin_, end)).toString();
 295  
     }
 296  
 
 297  
     /**
 298  
      * Removes the surrounding quote and any double quote inside the string <br>
 299  
      * Example:<br>
 300  
      * <pre>
 301  
      * "hello""world" becomes hello"world
 302  
      * </pre>
 303  
      *
 304  
      * @param str input string to dequote
 305  
      * @param quote the quoting char
 306  
      *
 307  
      * @return dequoted String
 308  
      */
 309  
     public static String dequoteFull(String str, char quote)
 310  
     {
 311  0
         if (str == null)
 312  
         {
 313  0
             return null;
 314  
         }
 315  
 
 316  0
         return dequoteFull(str, 0, str.length(), quote);
 317  
     }
 318  
 
 319  
     public static String dequoteFull(String str, int begin, int end, char quote)
 320  
     {
 321  
         // If empty substring, return empty string
 322  0
         if (begin == end)
 323  
         {
 324  0
             return "";
 325  
         }
 326  
 
 327  
         // If not quoted, return string
 328  0
         if (str.charAt(begin) != quote)
 329  
         {
 330  0
             return str.substring(begin, end);
 331  
         }
 332  
 
 333  0
         int _end = end - 1;
 334  0
         if ((str.length() < 2) || (str.charAt(_end) != quote))
 335  
         {
 336  0
             throw new IllegalArgumentException(
 337  
                 "Closing quote missing in string '"
 338  
                 + substring(str, begin, end) + "'");
 339  
         }
 340  
 
 341  0
         return dequote(str, begin + 1, _end, quote);
 342  
     }
 343  
 
 344  
     public static String replace(String str, String repl, String with)
 345  
     {
 346  0
         int lastindex = 0;
 347  0
         int pos = str.indexOf(repl);
 348  
 
 349  
         // If no replacement needed, return the original string
 350  
         // and save StringBuffer allocation/char copying
 351  0
         if (pos < 0)
 352  
         {
 353  0
             return str;
 354  
         }
 355  
 
 356  0
         int          len     = repl.length();
 357  0
         int          lendiff = with.length() - repl.length();
 358  0
         StringBuffer out     =
 359  
             new StringBuffer((lendiff <= 0) ? str.length()
 360  
                 : (str.length() + (10 * lendiff)));
 361  0
         for (; pos >= 0; pos = str.indexOf(repl, lastindex = pos + len))
 362  
         {
 363  0
             out.append(substring(str, lastindex, pos)).append(with);
 364  
         }
 365  
 
 366  0
         return out.append(substring(str, lastindex, str.length())).toString();
 367  
     }
 368  
 
 369  
     public static String replace(String str, char repl, String with)
 370  
     {
 371  0
         int pos = str.indexOf(repl);
 372  
 
 373  
         // If no replacement needed, return the original string
 374  
         // and save StringBuffer allocation/char copying
 375  0
         if (pos < 0)
 376  
         {
 377  0
             return str;
 378  
         }
 379  
 
 380  0
         int          len       = str.length();
 381  0
         int          lendiff   = with.length() - 1;
 382  0
         StringBuffer out       =
 383  
             new StringBuffer((lendiff <= 0) ? str.length()
 384  
                 : (str.length() + (10 * lendiff)));
 385  0
         int          lastindex = 0;
 386  0
         for (; pos >= 0; pos = str.indexOf(repl, lastindex = pos + 1))
 387  
         {
 388  0
             out.append(substring(str, lastindex, pos)).append(with);
 389  
         }
 390  
 
 391  0
         return out.append(substring(str, lastindex, len)).toString();
 392  
     }
 393  
 
 394  
     public static StringBuffer replace(
 395  
         StringBuffer out, String s, String repl, String with)
 396  
     {
 397  0
         int lastindex = 0;
 398  0
         int len = repl.length();
 399  0
         for (int index = s.indexOf(repl); index >= 0;
 400  0
                     index = s.indexOf(repl, lastindex = index + len))
 401  
         {
 402  
             // we have search string at position index
 403  0
             out.append(substring(s, lastindex, index)).append(with);
 404  
         }
 405  
 
 406  0
         return out.append(substring(s, lastindex, len));
 407  
     }
 408  
 
 409  
     /**
 410  
      * Split a string into an array of strings arround a character separator.
 411  
      * This  function will be efficient for longer strings
 412  
      *
 413  
      * @param str the string to be split
 414  
      * @param separator the separator character
 415  
      *
 416  
      * @return array of string subparts
 417  
      */
 418  
     public static String[] splitLongString(String str, char separator)
 419  
     {
 420  
         int len;
 421  0
         if (str == null || (len = str.length()) == 0)
 422  
         {
 423  0
             return ArrayUtils.EMPTY_STRING_ARRAY;
 424  
         }
 425  
 
 426  0
         int       oldPos = 0;
 427  0
         ArrayList list = new ArrayList();
 428  
         for (
 429  0
             int pos = str.indexOf(separator); pos >= 0;
 430  0
                     pos = str.indexOf(separator, (oldPos = (pos + 1))))
 431  
         {
 432  0
             list.add(substring(str, oldPos, pos));
 433  
         }
 434  
 
 435  0
         list.add(substring(str, oldPos, len));
 436  
 
 437  0
         return (String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
 438  
     }
 439  
 
 440  
     /**
 441  
      * Split a string into an array of strings arround a character separator.
 442  
      * Each element can be optionally quoted by the quote character.<br>
 443  
      * This function will be efficient for long strings
 444  
      *
 445  
      * @param str the string to be split
 446  
      * @param separator the separator character
 447  
      * @param quote the quote character
 448  
      *
 449  
      * @return array of string subparts
 450  
      *
 451  
      * @throws IllegalArgumentException DOCUMENT ME!
 452  
      */
 453  
     public static String[] splitLongString(
 454  
         String str, char separator, char quote)
 455  
     {
 456  
         int len;
 457  0
         if (str == null || (len = str.length()) == 0)
 458  
         {
 459  0
             return ArrayUtils.EMPTY_STRING_ARRAY;
 460  
         }
 461  
 
 462  0
         int       oldPos = 0;
 463  0
         ArrayList list = new ArrayList();
 464  0
         for (int pos = 0; pos < len; oldPos = ++pos)
 465  
         {
 466  
             // Skip quoted text, if any
 467  0
             while ((pos < len) && (str.charAt(pos) == quote))
 468  
             {
 469  0
                 pos = str.indexOf(quote, pos + 1) + 1;
 470  
 
 471  0
                 if (pos == 0)
 472  
                 {
 473  0
                     throw new IllegalArgumentException(
 474  
                         "Closing quote missing in string '" + str + "'");
 475  
                 }
 476  
             }
 477  
 
 478  
             boolean quoted;
 479  
 
 480  0
             if (pos != oldPos)
 481  
             {
 482  0
                 quoted = true;
 483  
 
 484  0
                 if ((pos < len) && (str.charAt(pos) != separator))
 485  
                 {
 486  0
                     throw new IllegalArgumentException(
 487  
                         "Separator must follow closing quote in string '"
 488  
                         + str + "'");
 489  
                 }
 490  
             }
 491  
             else
 492  
             {
 493  0
                 quoted     = false;
 494  0
                 pos        = str.indexOf(separator, pos);
 495  0
                 if (pos < 0)
 496  
                 {
 497  0
                     pos = len;
 498  
                 }
 499  
             }
 500  
 
 501  0
             list.add(
 502  
                 quoted ? dequote(str, oldPos + 1, pos - 1, quote)
 503  
                     : substring(str, oldPos, pos));
 504  
         }
 505  
 
 506  0
         return (String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
 507  
     }
 508  
 
 509  
     /**
 510  
      * Split a string into an array of strings arround a character separator.
 511  
      * This  function will be efficient for short strings, for longer strings,
 512  
      * another approach may be better
 513  
      *
 514  
      * @param str the string to be split
 515  
      * @param separator the separator character
 516  
      *
 517  
      * @return array of string subparts
 518  
      */
 519  
     public static String[] splitShortString(String str, char separator)
 520  
     {
 521  
         int len;
 522  0
         if (str == null || (len = str.length()) == 0)
 523  
         {
 524  0
             return org.apache.myfaces.shared_impl.util.ArrayUtils.EMPTY_STRING_ARRAY;
 525  
         }
 526  
 
 527  0
         int lastTokenIndex = 0;
 528  
 
 529  
         // Step 1: how many substrings?
 530  
         //      We exchange double scan time for less memory allocation
 531  0
         for (int pos = str.indexOf(separator);
 532  0
             pos >= 0; pos = str.indexOf(separator, pos + 1))
 533  
         {
 534  0
             lastTokenIndex++;
 535  
         }
 536  
 
 537  
         // Step 2: allocate exact size array
 538  0
         String[] list   = new String[lastTokenIndex + 1];
 539  
 
 540  0
         int      oldPos = 0;
 541  
 
 542  
         // Step 3: retrieve substrings
 543  
         for (
 544  0
             int pos = str.indexOf(separator), i = 0; pos >= 0;
 545  0
                     pos = str.indexOf(separator, (oldPos = (pos + 1))))
 546  
         {
 547  0
             list[i++] = substring(str, oldPos, pos);
 548  
         }
 549  
 
 550  0
         list[lastTokenIndex] = substring(str, oldPos, len);
 551  
 
 552  0
         return list;
 553  
     }
 554  
 
 555  
     /**
 556  
      * Split a string into an array of strings arround a character separator.
 557  
      * Each element can be optionally quoted by the quote character.<br>
 558  
      * This function will be efficient for short strings, for longer strings,
 559  
      * another approach may be better
 560  
      *
 561  
      * @param str the string to be split
 562  
      * @param separator the separator character
 563  
      * @param quote the quote character
 564  
      *
 565  
      * @return array of string subparts
 566  
      *
 567  
      * @throws IllegalArgumentException DOCUMENT ME!
 568  
      */
 569  
     public static String[] splitShortString(
 570  
         String str, char separator, char quote)
 571  
     {
 572  
         int len;
 573  0
         if (str == null || (len = str.length()) == 0)
 574  
         {
 575  0
             return ArrayUtils.EMPTY_STRING_ARRAY;
 576  
         }
 577  
 
 578  
         // Step 1: how many substrings?
 579  
         //      We exchange double scan time for less memory allocation
 580  0
         int tokenCount = 0;
 581  0
         for (int pos = 0; pos < len; pos++)
 582  
         {
 583  0
             tokenCount++;
 584  
 
 585  0
             int oldPos = pos;
 586  
 
 587  
             // Skip quoted text, if any
 588  0
             while ((pos < len) && (str.charAt(pos) == quote))
 589  
             {
 590  0
                 pos = str.indexOf(quote, pos + 1) + 1;
 591  
 
 592  
                 // pos == 0 is not found (-1 returned by indexOf + 1)
 593  0
                 if (pos == 0)
 594  
                 {
 595  0
                     throw new IllegalArgumentException(
 596  
                         "Closing quote missing in string '" + str + "'");
 597  
                 }
 598  
             }
 599  
 
 600  0
             if (pos != oldPos)
 601  
             {
 602  0
                 if ((pos < len) && (str.charAt(pos) != separator))
 603  
                 {
 604  0
                     throw new IllegalArgumentException(
 605  
                         "Separator must follow closing quote in strng '"
 606  
                         + str + "'");
 607  
                 }
 608  
             }
 609  
             else
 610  
             {
 611  0
                 pos = str.indexOf(separator, pos);
 612  0
                 if (pos < 0)
 613  
                 {
 614  0
                     break;
 615  
                 }
 616  
             }
 617  
         }
 618  
 
 619  
         // Main loop will finish one substring short when last char is separator
 620  0
         if (str.charAt(len - 1) == separator)
 621  
         {
 622  0
             tokenCount++;
 623  
         }
 624  
 
 625  
         // Step 2: allocate exact size array
 626  0
         String[] list = new String[tokenCount];
 627  
 
 628  
         // Step 3: retrieve substrings
 629  
         // Note: on this pass we do not check for correctness,
 630  
         //       since we have already done so
 631  0
         tokenCount--; // we want to stop one token short
 632  
 
 633  0
         int oldPos = 0;
 634  0
         for (int pos = 0, i = 0; i < tokenCount; i++, oldPos = ++pos)
 635  
         {
 636  
             boolean quoted;
 637  
 
 638  
             // Skip quoted text, if any
 639  0
             while (str.charAt(pos) == quote)
 640  
             {
 641  0
                 pos = str.indexOf(quote, pos + 1) + 1;
 642  
             }
 643  
 
 644  0
             if (pos != oldPos)
 645  
             {
 646  0
                 quoted = true;
 647  
 
 648  0
                 if (str.charAt(pos) != separator)
 649  
                 {
 650  0
                     throw new IllegalArgumentException(
 651  
                         "Separator must follow closing quote in strng '"
 652  
                         + str + "'");
 653  
                 }
 654  
             }
 655  
             else
 656  
             {
 657  0
                 quoted     = false;
 658  0
                 pos        = str.indexOf(separator, pos);
 659  
             }
 660  
 
 661  0
             list[i] =
 662  
                 quoted ? dequote(str, oldPos + 1, pos - 1, quote)
 663  
                     : substring(str, oldPos, pos);
 664  
         }
 665  
 
 666  0
         list[tokenCount] = dequoteFull(str, oldPos, len, quote);
 667  
 
 668  0
         return list;
 669  
     }
 670  
 
 671  
     public static String substring(String str, int begin, int end)
 672  
     {
 673  0
         if (begin == end)
 674  
         {
 675  0
             return "";
 676  
         }
 677  
 
 678  0
         return str.substring(begin, end);
 679  
     }
 680  
 
 681  
     public static String[] trim(String[] strings)
 682  
     {
 683  0
         if (strings == null)
 684  
         {
 685  0
             return null;
 686  
         }
 687  
 
 688  0
         for (int i = 0, len = strings.length; i < len; i++)
 689  
         {
 690  0
             strings[i] = strings[i].trim();
 691  
         }
 692  
 
 693  0
         return strings;
 694  
     }
 695  
 
 696  
     /**
 697  
      * Returns the minimum index >= 0, if any
 698  
      *
 699  
      * <p>
 700  
      * Use to find the first of two characters in a string:<br>
 701  
      * <code>minIndex(s.indexOf('/'), indexOf('\'))</code>
 702  
      * </p>
 703  
      *
 704  
      */
 705  
     public static int minIndex(int a, int b)
 706  
     {
 707  0
         return (a < 0) ? b
 708  
             : (b < 0) ? a
 709  
                 : (a < b) ? a : b;
 710  
     }
 711  
 }