Home | History | Annotate | Download | only in text
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4  *******************************************************************************
      5  * Copyright (C) 2001-2011, International Business Machines Corporation and    *
      6  * others. All Rights Reserved.                                                *
      7  *******************************************************************************
      8  */
      9 package com.ibm.icu.text;
     10 import com.ibm.icu.impl.Utility;
     11 
     12 class Quantifier implements UnicodeMatcher {
     13 
     14     private UnicodeMatcher matcher;
     15 
     16     private int minCount;
     17 
     18     private int maxCount;
     19 
     20     /**
     21      * Maximum count a quantifier can have.
     22      */
     23     public static final int MAX = Integer.MAX_VALUE;
     24 
     25     public Quantifier(UnicodeMatcher theMatcher,
     26                       int theMinCount, int theMaxCount) {
     27         if (theMatcher == null || theMinCount < 0 || theMaxCount < 0 || theMinCount > theMaxCount) {
     28             throw new IllegalArgumentException();
     29         }
     30         matcher = theMatcher;
     31         minCount = theMinCount;
     32         maxCount = theMaxCount;
     33     }
     34 
     35     /**
     36      * Implement UnicodeMatcher API.
     37      */
     38     public int matches(Replaceable text,
     39                        int[] offset,
     40                        int limit,
     41                        boolean incremental) {
     42         int start = offset[0];
     43         int count = 0;
     44         while (count < maxCount) {
     45             int pos = offset[0];
     46             int m = matcher.matches(text, offset, limit, incremental);
     47             if (m == U_MATCH) {
     48                 ++count;
     49                 if (pos == offset[0]) {
     50                     // If offset has not moved we have a zero-width match.
     51                     // Don't keep matching it infinitely.
     52                     break;
     53                 }
     54             } else if (incremental && m == U_PARTIAL_MATCH) {
     55                 return U_PARTIAL_MATCH;
     56             } else {
     57                 break;
     58             }
     59         }
     60         if (incremental && offset[0] == limit) {
     61             return U_PARTIAL_MATCH;
     62         }
     63         if (count >= minCount) {
     64             return U_MATCH;
     65         }
     66         offset[0] = start;
     67         return U_MISMATCH;
     68     }
     69 
     70     /**
     71      * Implement UnicodeMatcher API
     72      */
     73     public String toPattern(boolean escapeUnprintable) {
     74         StringBuilder result = new StringBuilder();
     75         result.append(matcher.toPattern(escapeUnprintable));
     76         if (minCount == 0) {
     77             if (maxCount == 1) {
     78                 return result.append('?').toString();
     79             } else if (maxCount == MAX) {
     80                 return result.append('*').toString();
     81             }
     82             // else fall through
     83         } else if (minCount == 1 && maxCount == MAX) {
     84             return result.append('+').toString();
     85         }
     86         result.append('{');
     87         result.append(Utility.hex(minCount,1));
     88         result.append(',');
     89         if (maxCount != MAX) {
     90             result.append(Utility.hex(maxCount,1));
     91         }
     92         result.append('}');
     93         return result.toString();
     94     }
     95 
     96     /**
     97      * Implement UnicodeMatcher API
     98      */
     99     public boolean matchesIndexValue(int v) {
    100         return (minCount == 0) || matcher.matchesIndexValue(v);
    101     }
    102 
    103     /**
    104      * Implementation of UnicodeMatcher API.  Union the set of all
    105      * characters that may be matched by this object into the given
    106      * set.
    107      * @param toUnionTo the set into which to union the source characters
    108      * @returns a reference to toUnionTo
    109      */
    110     public void addMatchSetTo(UnicodeSet toUnionTo) {
    111         if (maxCount > 0) {
    112             matcher.addMatchSetTo(toUnionTo);
    113         }
    114     }
    115 }
    116 
    117 //eof
    118