bool constructSafeLabels(const NxsTaxaBlock & tb, std::vector<std::string> * vs, std::set<std::string> & safeLabelSet) { if (vs == 0L) return false; const unsigned numTaxa = tb.GetNTaxTotal(); bool changed = false; for (unsigned i = 0; i < numTaxa; ++i) { NxsString oldName = tb.GetTaxonLabel(i); unsigned oldOffset = 0; unsigned newOffset = 0; std::string prefix; for (; newOffset < 10 && oldOffset < oldName.length(); ++oldOffset) { char c = oldName[oldOffset]; if ((isgraph(c)) && (strchr("!@#$%^&*.?|()[]{}/\\,;:=*\'\"`-+<>", c) == NULL)) { if (newOffset == 0 && isdigit(c)) { prefix.append(1, 't'); newOffset += 1; } prefix.append(1, toupper(c)); newOffset += 1; } } std::string newLabel = assignUniqueName(prefix, 10, safeLabelSet); safeLabelSet.insert(newLabel); vs->push_back(newLabel); if (newLabel != oldName) changed = true; } return changed; }
/*---------------------------------------------------------------------------------------------------------------------- | Right-justifies `x' in a field `w' characters wide with precision `p', using blank spaces to fill in unused | portions on the left-hand side of the field. Specify true for `clear_first' to first empty the string. Assumes that | the specified width is enough to accommodate the string representation of `x'. */ NxsString &NxsString::RightJustifyDbl( double x, /* double value to right justify */ unsigned w, /* width of field */ unsigned p, /* precision to use when displaying `x' */ bool clear_first) /* if true, initialize stored string first to the empty string */ { if (clear_first) erase(); char fmtstr[81]; sprintf(fmtstr, "%%.%df", p); NxsString tmp; tmp.PrintF(fmtstr, x); NCL_ASSERT(w >= tmp.length()); unsigned num_spaces = w - tmp.length(); for (unsigned k = 0; k < num_spaces; k++) *this += ' '; *this += tmp; return *this; }
bool formLegalPhylipName(const std::string & origName, const NxsString & numericExtension, const std::set<std::string> & used, std::string & toReturn) { const unsigned MAX_PHYLIP_NAME_LENGTH = 10; unsigned postLen = numericExtension.length(); if (postLen > MAX_PHYLIP_NAME_LENGTH) throw NxsException("Number of duplicate names exceed the capacity of our poorly thought out mechanism for avoiding name clashes"); const unsigned unPaddedLen = postLen + origName.length(); if (unPaddedLen <= MAX_PHYLIP_NAME_LENGTH) toReturn = origName; else if (postLen == MAX_PHYLIP_NAME_LENGTH) toReturn.clear(); else toReturn.assign(origName.c_str(), MAX_PHYLIP_NAME_LENGTH - postLen); toReturn.append(numericExtension.c_str()); if (unPaddedLen < MAX_PHYLIP_NAME_LENGTH) toReturn.append(MAX_PHYLIP_NAME_LENGTH - unPaddedLen, ' '); const std::string cap = NxsString::get_upper(toReturn); return (used.find(cap) == used.end()); }
/*---------------------------------------------------------------------------------------------------------------------- | Shortens stored string to `n' - 3 characters, making the last three characters "...". If string is already less than | `n' characters in length, this function has no effect. This is useful when it is desirable to show some of the | contents of a string, even when the string will not fit in its entirety into the space available for displaying it. | Assumes that `n' is at least 4. */ NxsString &NxsString::ShortenTo( unsigned n) /* maximum number of characters available for displaying the string */ { NCL_ASSERT(n > 3); if (length() <= static_cast<unsigned>(n)) return *this; NxsString s; for (NxsString::iterator sIt = begin(); sIt != end(); sIt++) { s += (*sIt); if (s.length() >= n - 3) break; } s += "..."; *this = s; return *this; }
std::string assignUniqueName(const std::string & prefix, unsigned maxLen, const std::set<std::string> & safeLabelSet) { NxsString s; s << prefix; std::set<std::string>::const_iterator sIt = safeLabelSet.find(s); if (sIt == safeLabelSet.end()) return s; unsigned i = 1; for (;;) { NxsString numAsStr; numAsStr << i++; s.clear(); unsigned concatLen = numAsStr.length() + prefix.length(); if (concatLen > maxLen) s << prefix.substr(0, 2*maxLen - 1 - concatLen); else s << prefix; s << numAsStr; sIt = safeLabelSet.find(s); if (sIt == safeLabelSet.end()) return s; } }