/** | returns the number of indices added. */ unsigned NxsSetReader::InterpretTokenAsIndices(NxsToken &token, const NxsLabelToIndicesMapper & mapper, const char * setType, const char * cmdName, NxsUnsignedSet * destination) { try { const std::string t = token.GetToken(); if (NxsString::case_insensitive_equals(t.c_str(), "ALL")) { unsigned m = mapper.GetMaxIndex(); NxsUnsignedSet s; for (unsigned i = 0; i <= m; ++i) s.insert(i); destination->insert(s.begin(), s.end()); return (unsigned)s.size(); } return mapper.GetIndicesForLabel(t, destination); } catch (const NxsException & x) { NxsString errormsg = "Error in the "; errormsg << setType << " descriptor of a " << cmdName << " command.\n"; errormsg += x.msg; throw NxsException(errormsg, token); } catch (...) { NxsString errormsg = "Expecting a "; errormsg << setType << " descriptor (number or label) in the " << cmdName << ". Encountered "; errormsg << token.GetToken(); throw NxsException(errormsg, token); } }
std::vector<unsigned> NxsSetReader::GetSetAsVector(const NxsUnsignedSet &s) { std::vector<unsigned> u; u.reserve(s.size()); for (NxsUnsignedSet::const_iterator sIt = s.begin(); sIt != s.end(); ++sIt) u.push_back(*sIt); return u; }
void NxsSetReader::ReadSetDefinition( NxsToken &token, const NxsLabelToIndicesMapper & mapper, const char * setType, /* "TAXON" or "CHARACTER" -- for error messages only */ const char * cmdName, /* command name -- "TAXSET" or "EXSET"-- for error messages only */ NxsUnsignedSet * destination, /** to be filled */ const NxsUnsignedSet * taboo) { NxsString errormsg; NxsUnsignedSet tmpset; NxsUnsignedSet dummy; if (destination == NULL) destination = & dummy; unsigned previousInd = UINT_MAX; std::vector<unsigned> intersectVec; while (!token.Equals(";")) { if (taboo && token.Equals(",")) return; if (token.Equals("-")) { if (previousInd == UINT_MAX) { errormsg = "The '-' must be preceded by number or a "; errormsg << setType << " label in the " << cmdName << " command."; throw NxsException(errormsg, token); } token.GetNextToken(); if (token.Equals(";") || token.Equals("\\")) { errormsg = "Range in the "; errormsg << setType << " set definition in the " << cmdName << " command must be closed with a number or label."; throw NxsException(errormsg, token); } unsigned endpoint; if (token.Equals(".")) endpoint = mapper.GetMaxIndex(); else { tmpset.clear(); unsigned nAdded = NxsSetReader::InterpretTokenAsIndices(token, mapper, setType, cmdName, &tmpset); if (nAdded != 1) { errormsg = "End of a range in a "; errormsg << setType << " set definition in the " << cmdName << " command must be closed with a single number or label (not a set)."; throw NxsException(errormsg, token); } endpoint = *(tmpset.begin()); if (endpoint < previousInd) { errormsg = "End of a range in a "; errormsg << setType << " set definition in the " << cmdName << " command must be a larger index than the start of the range (found "; errormsg << previousInd + 1 << " - " << token.GetToken(); throw NxsException(errormsg, token); } } token.GetNextToken(); if (token.Equals("\\")) { token.GetNextToken(); NxsString t = token.GetToken(); unsigned stride = 0; try { stride = t.ConvertToUnsigned(); } catch (const NxsString::NxsX_NotANumber &) {} if (stride == 0) { errormsg = "Expecting a positive number indicating the 'stride' after the \\ in the "; errormsg << setType << " set definition in the " << cmdName << " command. Encountered "; errormsg << t; throw NxsException(errormsg, token); } AddRangeToSet(previousInd, endpoint, stride, destination, taboo, token); token.GetNextToken(); } else AddRangeToSet(previousInd, endpoint, 1, destination, taboo, token); previousInd = UINT_MAX; } else { tmpset.clear(); const unsigned nAdded = NxsSetReader::InterpretTokenAsIndices(token, mapper, setType, cmdName, &tmpset); if (taboo != NULL) { set_intersection(taboo->begin(), taboo->end(), tmpset.begin(), tmpset.end(), back_inserter(intersectVec)); if (!intersectVec.empty()) { errormsg << "Illegal repitition of an index (" << 1 + *(intersectVec.begin()) << ") in multiple subsets."; throw NxsException(errormsg, token); } } if (nAdded == 1 ) { previousInd = *(tmpset.begin()); destination->insert(previousInd); } else { previousInd = UINT_MAX; destination->insert(tmpset.begin(), tmpset.end()); } token.GetNextToken(); } } }
void NxsSetReader::WriteSetAsNexusValue(const NxsUnsignedSet & nxsset, std::ostream & out) { NxsUnsignedSet::const_iterator currIt = nxsset.begin(); const NxsUnsignedSet::const_iterator endIt = nxsset.end(); if (currIt == endIt) return; unsigned rangeBegin = 1 + *currIt++; if (currIt == endIt) { out << ' ' << rangeBegin; return; } unsigned prev = 1 + *currIt++; if (currIt == endIt) { out << ' ' << rangeBegin << ' ' << prev; return; } unsigned stride = prev - rangeBegin; unsigned curr = 1 + *currIt++; bool inRange = true; while (currIt != endIt) { if (inRange) { if (curr - prev != stride) { if (prev - rangeBegin == stride) { out << ' ' << rangeBegin; rangeBegin = prev; stride = curr - prev; } else { if (stride > 1) out << ' ' << rangeBegin << '-' << prev << " \\ " << stride; else out << ' ' << rangeBegin << '-' << prev ; inRange = false; } } } else { inRange = true; rangeBegin = prev; stride = curr - prev; } prev = curr; curr = 1 + *currIt; currIt++; } if (inRange) { if (curr - prev != stride) { if (prev - rangeBegin == stride) out << ' ' << rangeBegin << ' ' << prev; else { if (stride > 1) out << ' ' << rangeBegin << '-' << prev << " \\ " << stride; else out << ' ' << rangeBegin << '-' << prev ; } out << ' ' << curr; } else { if (stride > 1) out << ' ' << rangeBegin << '-' << curr << " \\ " << stride; else out << ' ' << rangeBegin << '-' << curr ; } } else out << ' ' << prev << ' ' << curr; }