String StringUtil::Implode(const Variant& items, const String& delim) { if (!isContainer(items)) { throw_param_is_not_container(); } int size = getContainerSize(items); if (size == 0) return ""; String* sitems = (String*)smart_malloc(size * sizeof(String)); int len = 0; int lenDelim = delim.size(); int i = 0; for (ArrayIter iter(items); iter; ++iter) { new (&sitems[i]) String(iter.second().toString()); len += sitems[i].size() + lenDelim; i++; } len -= lenDelim; // always one delimiter less than count of items assert(i == size); String s = String(len, ReserveString); char *buffer = s.bufferSlice().ptr; const char *sdelim = delim.data(); char *p = buffer; for (int i = 0; i < size; i++) { String &item = sitems[i]; if (i && lenDelim) { memcpy(p, sdelim, lenDelim); p += lenDelim; } int lenItem = item.size(); if (lenItem) { memcpy(p, item.data(), lenItem); p += lenItem; } sitems[i].~String(); } smart_free(sitems); assert(p - buffer == len); s.setSize(len); return s; }
String StringUtil::Implode(const Variant& items, const String& delim, const bool checkIsContainer /* = true */) { if (checkIsContainer && !isContainer(items)) { throw_param_is_not_container(); } int size = getContainerSize(items); if (size == 0) return empty_string(); req::vector<String> sitems; sitems.reserve(size); size_t len = 0; size_t lenDelim = delim.size(); for (ArrayIter iter(items); iter; ++iter) { sitems.emplace_back(iter.second().toString()); len += sitems.back().size() + lenDelim; } len -= lenDelim; // always one delimiter less than count of items assert(sitems.size() == size); String s = String(len, ReserveString); char *buffer = s.mutableData(); const char *sdelim = delim.data(); char *p = buffer; String &init_str = sitems[0]; int init_len = init_str.size(); memcpy(p, init_str.data(), init_len); p += init_len; for (int i = 1; i < size; i++) { String &item = sitems[i]; memcpy(p, sdelim, lenDelim); p += lenDelim; int lenItem = item.size(); memcpy(p, item.data(), lenItem); p += lenItem; } assert(p - buffer == len); s.setSize(len); return s; }