private Set<String> extract(int comp, String segment, int segmentPos, StringBuffer buf) {
        if (PROGRESS) System.out.println(" extract: " + Utility.hex(UTF16.valueOf(comp))
            + ", " + Utility.hex(segment.substring(segmentPos)));

        String decomp = nfcImpl.getDecomposition(comp);
        if (decomp == null) {
            decomp = UTF16.valueOf(comp);
        }

        // See if it matches the start of segment (at segmentPos)
        boolean ok = false;
        int cp;
        int decompPos = 0;
        int decompCp = UTF16.charAt(decomp,0);
        decompPos += UTF16.getCharCount(decompCp); // adjust position to skip first char
        //int decompClass = getClass(decompCp);
        buf.setLength(0); // initialize working buffer, shared among callees

        for (int i = segmentPos; i < segment.length(); i += UTF16.getCharCount(cp)) {
            cp = UTF16.charAt(segment, i);
            if (cp == decompCp) { // if equal, eat another cp from decomp
                if (PROGRESS) System.out.println("  matches: " + Utility.hex(UTF16.valueOf(cp)));
                if (decompPos == decomp.length()) { // done, have all decomp characters!
                    buf.append(segment.substring(i + UTF16.getCharCount(cp))); // add remaining segment chars
                    ok = true;
                    break;
                }
                decompCp = UTF16.charAt(decomp, decompPos);
                decompPos += UTF16.getCharCount(decompCp);
                //decompClass = getClass(decompCp);
            } else {
                if (PROGRESS) System.out.println("  buffer: " + Utility.hex(UTF16.valueOf(cp)));
                // brute force approach
                UTF16.append(buf, cp);
                /* TODO: optimize
                // since we know that the classes are monotonically increasing, after zero
                // e.g. 0 5 7 9 0 3
                // we can do an optimization
                // there are only a few cases that work: zero, less, same, greater
                // if both classes are the same, we fail
                // if the decomp class < the segment class, we fail

                segClass = getClass(cp);
                if (decompClass <= segClass) return null;
                */
            }
        }
        if (!ok) return null; // we failed, characters left over
        if (PROGRESS) System.out.println("Matches");
        if (buf.length() == 0) return SET_WITH_NULL_STRING; // succeed, but no remainder
        String remainder = buf.toString();

        // brute force approach
        // to check to make sure result is canonically equivalent
        /*
        String trial = Normalizer.normalize(UTF16.valueOf(comp) + remainder, Normalizer.DECOMP, 0);
        if (!segment.regionMatches(segmentPos, trial, 0, segment.length() - segmentPos)) return null;
        */

        if (0!=Normalizer.compare(UTF16.valueOf(comp) + remainder, segment.substring(segmentPos), 0)) return null;

        // get the remaining combinations
        return getEquivalents2(remainder);
    }
private Set < String > extract ( int comp , String segment , int segmentPos , StringBuffer buf ) { if ( PROGRESS ) System . out . println ( " extract: " + Utility . hex ( UTF16 . valueOf ( comp ) ) + ", " + Utility . hex ( segment . substring ( segmentPos ) ) ) ; String decomp = nfcImpl . getDecomposition ( comp ) ; if ( decomp == null ) { decomp = UTF16 . valueOf ( comp ) ; } boolean ok = false ; int cp ; int decompPos = 0 ; int decompCp = UTF16 . charAt ( decomp , 0 ) ; decompPos += UTF16 . getCharCount ( decompCp ) ; buf . setLength ( 0 ) ; for ( int i = segmentPos ; i < segment . length ( ) ; i += UTF16 . getCharCount ( cp ) ) { cp = UTF16 . charAt ( segment , i ) ; if ( cp == decompCp ) { if ( PROGRESS ) System . out . println ( "  matches: " + Utility . hex ( UTF16 . valueOf ( cp ) ) ) ; if ( decompPos == decomp . length ( ) ) { buf . append ( segment . substring ( i + UTF16 . getCharCount ( cp ) ) ) ; ok = true ; break ; } decompCp = UTF16 . charAt ( decomp , decompPos ) ; decompPos += UTF16 . getCharCount ( decompCp ) ; } else { if ( PROGRESS ) System . out . println ( "  buffer: " + Utility . hex ( UTF16 . valueOf ( cp ) ) ) ; UTF16 . append ( buf , cp ) ; } } if ( ! ok ) return null ; if ( PROGRESS ) System . out . println ( "Matches" ) ; if ( buf . length ( ) == 0 ) return SET_WITH_NULL_STRING ; String remainder = buf . toString ( ) ; if ( 0 != Normalizer . compare ( UTF16 . valueOf ( comp ) + remainder , segment . substring ( segmentPos ) , 0 ) ) return null ; return getEquivalents2 ( remainder ) ; }
See if the decomposition of cp2 is at segment starting at segmentPos
(with canonical rearrangment!)
If so, take the remainder, and return the equivalents