private IRubyObject gsubCommon(Regex regex, ThreadContext context, final boolean bang, final boolean iter, RubyRegexp rubyRegex, Block block, IRubyObject repl, boolean tainted) {
int begin = value.begin;
int range = begin + value.realSize;
Matcher matcher = regex.matcher(value.bytes, begin, range);
int beg = matcher.search(begin, range, Option.NONE);
Frame frame = context.getPreviousFrame();
if (beg < 0) {
frame.setBackRef(context.getRuntime().getNil());
return bang ? context.getRuntime().getNil() : strDup(context.getRuntime()); /* bang: true, no match, no substitution */
}
int blen = value.realSize + 30; /* len + margin */
ByteList dest = new ByteList(blen);
dest.realSize = blen;
int buf = 0;
int bp = 0;
int cp = begin;
int offset = 0;
RubyString val;
RubyMatchData match = null;
while (beg >= 0) {
final int begz;
final int endz;
if (iter) {
byte[] bytes = value.bytes;
int size = value.realSize;
match = rubyRegex.updateBackRef(context, this, frame, matcher);
match.use();
if (regex.numberOfCaptures() == 0) {
begz = matcher.getBegin();
endz = matcher.getEnd();
val = objAsString(context, block.yield(context, substr(context.getRuntime(), begz, endz - begz)));
} else {
Region region = matcher.getRegion();
begz = region.beg[0];
endz = region.end[0];
val = objAsString(context, block.yield(context, substr(context.getRuntime(), begz, endz - begz)));
}
modifyCheck(bytes, size);
if (bang) {
frozenCheck();
}
} else {
val = rubyRegex.regsub((RubyString) repl, this, matcher);
if (regex.numberOfCaptures() == 0) {
begz = matcher.getBegin();
endz = matcher.getEnd();
} else {
Region region = matcher.getRegion();
begz = region.beg[0];
endz = region.end[0];
}
}
if (val.isTaint()) {
tainted = true;
}
ByteList vbuf = val.value;
int len = (bp - buf) + (beg - offset) + vbuf.realSize + 3;
if (blen < len) {
while (blen < len) {
blen <<= 1;
}
len = bp - buf;
dest.realloc(blen);
dest.realSize = blen;
bp = buf + len;
}
len = beg - offset; /* copy pre-match substr */
System.arraycopy(value.bytes, cp, dest.bytes, bp, len);
bp += len;
System.arraycopy(vbuf.bytes, vbuf.begin, dest.bytes, bp, vbuf.realSize);
bp += vbuf.realSize;
offset = endz;
if (begz == endz) {
if (value.realSize <= endz) {
break;
}
len = regex.getEncoding().length(value.bytes, begin + endz, range);
System.arraycopy(value.bytes, begin + endz, dest.bytes, bp, len);
bp += len;
offset = endz + len;
}
cp = begin + offset;
if (offset > value.realSize) {
break;
}
beg = matcher.search(cp, range, Option.NONE);
}
if (value.realSize > offset) {
int len = bp - buf;
if (blen - len < value.realSize - offset) {