code: private ImmutableList<CharacterRegion> canonicalize(ImmutableList<CharacterRegion> inputRegions) {
      boolean mergedAnything = false;
      final ImmutableList.Builder<CharacterRegion> canonicalizedRegions = ImmutableList.builder();
      CharacterRegion bufferRegion = null;
  
      for (final CharacterRegion curRegion : inputRegions) {
        if (bufferRegion == null) {
          bufferRegion = curRegion;
        } else {
          if (bufferRegion.mayMergeWithFollowing(curRegion)) {
            mergedAnything = true;
            bufferRegion = bufferRegion.mergeFollowingRegion(curRegion);
          } else {
            canonicalizedRegions.add(bufferRegion);
            bufferRegion = curRegion;
          }
        }
      }
  
      if (bufferRegion != null) {
        canonicalizedRegions.add(bufferRegion);
      }
  
      if (mergedAnything) {
        return canonicalizedRegions.build();
      } else {
        return inputRegions;
      }
    }
docs: Converts character regions into a canonical form where no two adjacent character regions have
  the same offset mapping rules (that is, there is no unnecessary multiplication of character
  regions).  We exploit this property when computing substring containment and doing equality
  checks.
  
  If the input is in canonical form already, the identical list object itself is returned.