int vsize = typedValue != null ? typedValue.size() : listValue.size();
// note that the base can have duplicate names, even though these cannot be created using update vector (like here),
// they can be created e.g. using names<- or with the c() builtin
Names bnames = base.names();
RSymbol[] bsymbols;
HashMap<RSymbol, Integer> nmap;
if (bnames == null) {
nmap = new HashMap<>(bsize);
bsymbols = null;
} else {
assert Utils.check(Names.keepsMap()); // FIXME: re-visit this if we re-introduce names that don't carry hashmaps
// (probably should build a new one in such a case)
nmap = new HashMap<>(bnames.getMap());
bsymbols = bnames.sequence();
}
RSymbol[] addSymbols = new RSymbol[isize];
int j = 0;
// NOTE: targetOffsets is here to avoid double lookup via the hashmap
// NOTE: firstOverwrite is here to make targetOffsets smaller in the quite common case that no (or little) new symbols are added
int firstOverwrite = -1;
int noverwrites = 0;
int[] targetOffsets = null;
for (int i = 0; i < isize; i++) {
RSymbol name = RSymbol.getSymbol(index.getString(i));
if (name == RSymbol.EMPTY_SYMBOL || name == RSymbol.NA_SYMBOL) { // these should never go to the map
addSymbols[j] = name;
if (targetOffsets != null) {
targetOffsets[i - firstOverwrite] = j + bsize;
}
j++;
} else {
Integer prevOffset = nmap.get(name);
if (prevOffset == null) {
nmap.put(name, j + bsize);
addSymbols[j] = name;
if (targetOffsets != null) {
targetOffsets[i - firstOverwrite] = j + bsize;
}
j++;
} else {
if (firstOverwrite == -1) {
firstOverwrite = i;
targetOffsets = new int[isize - firstOverwrite];
}
noverwrites++;
targetOffsets[i - firstOverwrite] = prevOffset.intValue();
}
}
}
int addSize = isize - noverwrites;
int nsize = bsize + addSize;
Names nnames;
if (addSize == 0) {
nnames = bnames;
} else if (bsize == 0) {
nnames = Names.create(addSymbols, nmap);
} else {