DateTimeNumericFieldElement::DateTimeNumericFieldElement( Document& document, FieldOwner& fieldOwner, const Range& range, const Range& hardLimits, const String& placeholder, const DateTimeNumericFieldElement::Step& step) : DateTimeFieldElement(document, fieldOwner), m_placeholder(placeholder), m_range(range), m_hardLimits(hardLimits), m_step(step), m_value(0), m_hasValue(false) { DCHECK_NE(m_step.step, 0); DCHECK_LE(m_range.minimum, m_range.maximum); DCHECK_LE(m_hardLimits.minimum, m_hardLimits.maximum); // We show a direction-neutral string such as "--" as a placeholder. It // should follow the direction of numeric values. if (localeForOwner().isRTL()) { CharDirection dir = direction(formatValue(this->maximum())[0]); if (dir == LeftToRight || dir == EuropeanNumber || dir == ArabicNumber) { setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueBidiOverride); setInlineStyleProperty(CSSPropertyDirection, CSSValueLtr); } } }
IOBuf IOBuf::cloneCoalescedAsValue() const { if (!isChained()) { return cloneOneAsValue(); } // Coalesce into newBuf const uint64_t newLength = computeChainDataLength(); const uint64_t newHeadroom = headroom(); const uint64_t newTailroom = prev()->tailroom(); const uint64_t newCapacity = newLength + newHeadroom + newTailroom; IOBuf newBuf{CREATE, newCapacity}; newBuf.advance(newHeadroom); auto current = this; do { if (current->length() > 0) { DCHECK_NOTNULL(current->data()); DCHECK_LE(current->length(), newBuf.tailroom()); memcpy(newBuf.writableTail(), current->data(), current->length()); newBuf.append(current->length()); } current = current->next(); } while (current != this); DCHECK_EQ(newLength, newBuf.length()); DCHECK_EQ(newHeadroom, newBuf.headroom()); DCHECK_LE(newTailroom, newBuf.tailroom()); return newBuf; }
int FieldTrial::AppendGroup(const std::string& name, Probability group_probability) { DCHECK_LE(group_probability, divisor_); DCHECK_GE(group_probability, 0); if(enable_benchmarking_ || !enable_field_trial_) { group_probability = 0; } accumulated_group_probability_ += group_probability; DCHECK_LE(accumulated_group_probability_, divisor_); if(group_==kNotFinalized && accumulated_group_probability_>random_) { // This is the group that crossed the random line, so we do the assignment. group_ = next_group_number_; if(name.empty()) { StringAppendF(&group_name_, "%d", group_); } else { group_name_ = name; } FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_); } return next_group_number_++; }
DeleteFromTextNodeCommand::DeleteFromTextNodeCommand(Text* node, unsigned offset, unsigned count) : SimpleEditCommand(node->document()), m_node(node), m_offset(offset), m_count(count) { DCHECK(m_node); DCHECK_LE(m_offset, m_node->length()); DCHECK_LE(m_offset + m_count, m_node->length()); }
CHARRANGE Range::ToCHARRANGE() const { CHARRANGE r = { -1, -1 }; if(!IsValid()) { return r; } const LONG kLONGMax = std::numeric_limits<LONG>::max(); DCHECK_LE(static_cast<LONG>(start()), kLONGMax); DCHECK_LE(static_cast<LONG>(end()), kLONGMax); r.cpMin = start(); r.cpMax = end(); return r; }
bool SplitStringIntoKeyValuePairs( const std::string& line, char key_value_delimiter, char key_value_pair_delimiter, std::vector<std::pair<std::string, std::string> >* kv_pairs) { kv_pairs->clear(); std::vector<std::string> pairs; SplitString(line, key_value_pair_delimiter, &pairs); bool success = true; for(size_t i=0; i<pairs.size(); ++i) { // 空键值对. SplitStringIntoKeyValues不识别空行, 继续下一个键值对. if(pairs[i].empty()) { continue; } std::string key; std::vector<std::string> value; if(!SplitStringIntoKeyValues(pairs[i], key_value_delimiter, &key, &value)) { // 这里不返回, 允许键不关联值; 仅标记切分失败. success = false; } DCHECK_LE(value.size(), 1U); kv_pairs->push_back(make_pair(key, value.empty()?"":value[0])); } return success; }
Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) { io_event events[pending_]; int count; do { // Wait forever count = io_getevents(ctx_, minRequests, maxRequests, events, nullptr); } while (count == -EINTR); checkKernelError(count, "AsyncIO: io_getevents failed"); DCHECK_GE(count, minRequests); // the man page says so DCHECK_LE(count, pending_); completed_.clear(); if (count == 0) { return folly::Range<Op**>(); } for (size_t i = 0; i < count; ++i) { DCHECK(events[i].obj); Op* op = boost::intrusive::get_parent_from_member( events[i].obj, &AsyncIOOp::iocb_); --pending_; op->complete(events[i].res); completed_.push_back(op); } return folly::Range<Op**>(&completed_.front(), count); }
void MarkupFormatter::appendCharactersReplacingEntities(StringBuilder& result, const String& source, unsigned offset, unsigned length, EntityMask entityMask) { DEFINE_STATIC_LOCAL(const CString, ampReference, ("&")); DEFINE_STATIC_LOCAL(const CString, ltReference, ("<")); DEFINE_STATIC_LOCAL(const CString, gtReference, (">")); DEFINE_STATIC_LOCAL(const CString, quotReference, (""")); DEFINE_STATIC_LOCAL(const CString, nbspReference, (" ")); DEFINE_STATIC_LOCAL(const CString, tabReference, ("	")); DEFINE_STATIC_LOCAL(const CString, lineFeedReference, (" ")); DEFINE_STATIC_LOCAL(const CString, carriageReturnReference, (" ")); static const EntityDescription entityMaps[] = { { '&', ampReference, EntityAmp }, { '<', ltReference, EntityLt }, { '>', gtReference, EntityGt }, { '"', quotReference, EntityQuot }, { noBreakSpaceCharacter, nbspReference, EntityNbsp }, { '\t', tabReference, EntityTab }, { '\n', lineFeedReference, EntityLineFeed }, { '\r', carriageReturnReference, EntityCarriageReturn }, }; if (!(offset + length)) return; DCHECK_LE(offset + length, source.length()); if (source.is8Bit()) appendCharactersReplacingEntitiesInternal(result, source.characters8() + offset, length, entityMaps, WTF_ARRAY_LENGTH(entityMaps), entityMask); else appendCharactersReplacingEntitiesInternal(result, source.characters16() + offset, length, entityMaps, WTF_ARRAY_LENGTH(entityMaps), entityMask); }
ScriptProcessorHandler::ScriptProcessorHandler(AudioNode& node, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels) : AudioHandler(NodeTypeJavaScript, node, sampleRate), m_doubleBufferIndex(0), m_bufferSize(bufferSize), m_bufferReadWriteIndex(0), m_numberOfInputChannels(numberOfInputChannels), m_numberOfOutputChannels(numberOfOutputChannels), m_internalInputBus(AudioBus::create(numberOfInputChannels, AudioUtilities::kRenderQuantumFrames, false)) { // Regardless of the allowed buffer sizes, we still need to process at the // granularity of the AudioNode. if (m_bufferSize < AudioUtilities::kRenderQuantumFrames) m_bufferSize = AudioUtilities::kRenderQuantumFrames; DCHECK_LE(numberOfInputChannels, BaseAudioContext::maxNumberOfChannels()); addInput(); addOutput(numberOfOutputChannels); m_channelCount = numberOfInputChannels; setInternalChannelCountMode(Explicit); initialize(); }
void StereoPannerHandler::process(size_t framesToProcess) { AudioBus* outputBus = output(0).bus(); if (!isInitialized() || !input(0).isConnected() || !m_stereoPanner.get()) { outputBus->zero(); return; } AudioBus* inputBus = input(0).bus(); if (!inputBus) { outputBus->zero(); return; } if (m_pan->hasSampleAccurateValues()) { // Apply sample-accurate panning specified by AudioParam automation. DCHECK_LE(framesToProcess, m_sampleAccuratePanValues.size()); if (framesToProcess <= m_sampleAccuratePanValues.size()) { float* panValues = m_sampleAccuratePanValues.data(); m_pan->calculateSampleAccurateValues(panValues, framesToProcess); m_stereoPanner->panWithSampleAccurateValues(inputBus, outputBus, panValues, framesToProcess); } } else { m_stereoPanner->panToTargetValue(inputBus, outputBus, m_pan->value(), framesToProcess); } }
/** * @brief Make a TypedValue of this Type. * * @param value_ptr An untyped pointer to the data which will be represented * as a TypedValue. * @param value_size The size of the data at value_ptr in bytes. This may be * omitted for numeric types, but must be explicitly specified for any * other type. For Char and VarChar, this should include the * terminating null character, if any. * @return A TypedValue representing the data at value_ptr. **/ inline TypedValue makeValue(const void* value_ptr, const std::size_t value_size = 0) const { DCHECK(value_ptr != nullptr); switch (type_id_) { case kInt: return TypedValue(*static_cast<const int*>(value_ptr)); case kLong: return TypedValue(*static_cast<const std::int64_t*>(value_ptr)); case kFloat: return TypedValue(*static_cast<const float*>(value_ptr)); case kDouble: return TypedValue(*static_cast<const double*>(value_ptr)); case kDatetime: return TypedValue(*static_cast<const DatetimeLit*>(value_ptr)); case kDatetimeInterval: return TypedValue(*static_cast<const DatetimeIntervalLit*>(value_ptr)); case kYearMonthInterval: return TypedValue(*static_cast<const YearMonthIntervalLit*>(value_ptr)); case kNullType: { LOG(FATAL) << "Calling makeValue() to make a non-null value for " << "NullType, which is impossible."; } default: DCHECK_NE(value_size, 0u); DCHECK_LE(value_size, maximum_byte_length_); return TypedValue(type_id_, value_ptr, value_size); } }
void PopHeader() { DCHECK(!empty()); const Header* h = _header_queue.top(); const size_t entry_size = HeaderSize(*h); DCHECK_LE(entry_size, size()); const uint64_t id = _add_times - _header_queue.size(); RemoveHeaderFromIndexes(*h, id); _size -= entry_size; _header_queue.pop(); }
int GetIndexOfName(const std::string& name) { DCHECK(_need_indexes); const uint64_t* v = _name_index.seek(name); if (!v) { return 0; } DCHECK_LE(_add_times - *v, _header_queue.size()); // The latest added entry has the smallest index return _start_index + (_add_times - *v) - 1; }
int GetIndexOfHeader(const Header& h) { DCHECK(_need_indexes); const uint64_t* v = _header_index.seek(h); if (!v) { return 0; } DCHECK_LE(_add_times - *v, _header_queue.size()); // The latest added entry has the smallest index return _start_index + (_add_times - *v) - 1; }
int RandInt(int min, int max) { DCHECK(min <= max); uint64 range = static_cast<uint64>(max) - min + 1; int result = min + static_cast<int>(RandGenerator(range)); DCHECK_GE(result, min); DCHECK_LE(result, max); return result; }
InsertIntoTextNodeCommand::InsertIntoTextNodeCommand(Text* node, unsigned offset, const String& text) : SimpleEditCommand(node->document()), m_node(node), m_offset(offset), m_text(text) { DCHECK(m_node); DCHECK_LE(m_offset, m_node->length()); DCHECK(!m_text.isEmpty()); }
void TextIteratorTextState::emitText(Node* textNode, LayoutText* layoutObject, int textStartOffset, int textEndOffset) { DCHECK(textNode); m_text = m_emitsOriginalText ? layoutObject->originalText() : layoutObject->text(); DCHECK(!m_text.isEmpty()); DCHECK_LE(0, textStartOffset); DCHECK_LT(textStartOffset, static_cast<int>(m_text.length())); DCHECK_LE(0, textEndOffset); DCHECK_LE(textEndOffset, static_cast<int>(m_text.length())); DCHECK_LE(textStartOffset, textEndOffset); m_positionNode = textNode; m_positionOffsetBaseNode = nullptr; m_positionStartOffset = textStartOffset; m_positionEndOffset = textEndOffset; m_singleCharacterBuffer = 0; m_textLength = textEndOffset - textStartOffset; m_lastCharacter = m_text[textEndOffset - 1]; m_hasEmitted = true; }
const char* WStatus::GetLastDate(int days_ago) const { DCHECK_GE(days_ago, 0); DCHECK_LE(days_ago, 2); switch (days_ago) { case 0: return m_pStatusRecord->date1; case 1: return m_pStatusRecord->date2; case 2: return m_pStatusRecord->date3; default: return m_pStatusRecord->date1; } }
inline AudioNodeOutput::AudioNodeOutput(AudioHandler* handler, unsigned numberOfChannels) : m_handler(*handler), m_numberOfChannels(numberOfChannels), m_desiredNumberOfChannels(numberOfChannels), m_isInPlace(false), m_isEnabled(true), m_didCallDispose(false), m_renderingFanOutCount(0), m_renderingParamFanOutCount(0) { DCHECK_LE(numberOfChannels, BaseAudioContext::maxNumberOfChannels()); m_internalBus = AudioBus::create(numberOfChannels, AudioUtilities::kRenderQuantumFrames); }
void AudioNodeOutput::setNumberOfChannels(unsigned numberOfChannels) { DCHECK_LE(numberOfChannels, BaseAudioContext::maxNumberOfChannels()); ASSERT(deferredTaskHandler().isGraphOwner()); m_desiredNumberOfChannels = numberOfChannels; if (deferredTaskHandler().isAudioThread()) { // If we're in the audio thread then we can take care of it right away (we // should be at the very start or end of a rendering quantum). updateNumberOfChannels(); } else { DCHECK(!m_didCallDispose); // Let the context take care of it in the audio thread in the pre and post // render tasks. deferredTaskHandler().markAudioNodeOutputDirty(this); } }
char* Pickle::BeginWrite(size_t length) { // uint32对齐位置开始写. size_t offset = AlignInt(header_->payload_size, sizeof(uint32)); size_t new_size = offset + length; size_t needed_size = header_size_ + new_size; if(needed_size>capacity_ && !Resize(std::max(capacity_*2, needed_size))) { return NULL; } #ifdef ARCH_CPU_64_BITS DCHECK_LE(length, std::numeric_limits<uint32>::max()); #endif header_->payload_size = static_cast<uint32>(new_size); return payload() + offset; }
void TruncateUTF8ToByteSize(const std::string& input, const size_t byte_size, std::string* output) { DCHECK(output); if(byte_size > input.length()) { *output = input; return; } DCHECK_LE(byte_size, static_cast<uint32>(kint32max)); // 注意: 由于CBU8_NEXT使用的是int32. int32 truncation_length = static_cast<int32>(byte_size); int32 char_index = truncation_length - 1; const char* data = input.data(); // 使用CBU8, 从阶段点由后向前移动查找合法的UTF8字符. 一旦找到 // 一个UTF8字符, 截断到该字符作为输出. while(char_index >= 0) { int32 prev = char_index; uint32 code_point = 0; CBU8_NEXT(data, char_index, truncation_length, code_point); if(!base::IsValidCharacter(code_point) || !base::IsValidCodepoint(code_point)) { char_index = prev - 1; } else { break; } } if(char_index >= 0) { *output = input.substr(0, char_index); } else { output->clear(); } }
KeyframeEffectModelBase::KeyframeVector KeyframeEffectModelBase::normalizedKeyframes(const KeyframeVector& keyframes) { double lastOffset = 0; KeyframeVector result; result.reserveCapacity(keyframes.size()); for (const auto& keyframe : keyframes) { double offset = keyframe->offset(); if (!isNull(offset)) { DCHECK_GE(offset, 0); DCHECK_LE(offset, 1); DCHECK_GE(offset, lastOffset); lastOffset = offset; } result.push_back(keyframe->clone()); } if (result.isEmpty()) return result; if (isNull(result.back()->offset())) result.back()->setOffset(1); if (result.size() > 1 && isNull(result[0]->offset())) result.front()->setOffset(0); size_t lastIndex = 0; lastOffset = result.front()->offset(); for (size_t i = 1; i < result.size(); ++i) { double offset = result[i]->offset(); if (!isNull(offset)) { for (size_t j = 1; j < i - lastIndex; ++j) result[lastIndex + j]->setOffset( lastOffset + (offset - lastOffset) * j / (i - lastIndex)); lastIndex = i; lastOffset = offset; } } return result; }
Range<AsyncIO::Op**> AsyncIO::pollCompleted() { CHECK(ctx_); CHECK_NE(pollFd_, -1) << "pollCompleted() only allowed on pollable object"; uint64_t numEvents; // This sets the eventFd counter to 0, see // http://www.kernel.org/doc/man-pages/online/pages/man2/eventfd.2.html ssize_t rc; do { rc = ::read(pollFd_, &numEvents, 8); } while (rc == -1 && errno == EINTR); if (UNLIKELY(rc == -1 && errno == EAGAIN)) { return Range<Op**>(); // nothing completed } checkUnixError(rc, "AsyncIO: read from event fd failed"); DCHECK_EQ(rc, 8); DCHECK_GT(numEvents, 0); DCHECK_LE(numEvents, pending_); // Don't reap more than numEvents, as we've just reset the counter to 0. return doWait(numEvents, numEvents); }
Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) { io_event events[maxRequests]; size_t count = 0; do { int ret; do { // GOTCHA: io_getevents() may returns less than min_nr results if // interrupted after some events have been read (if before, -EINTR // is returned). ret = io_getevents(ctx_, minRequests - count, maxRequests - count, events + count, /* timeout */ nullptr); // wait forever } while (ret == -EINTR); // Check as may not be able to recover without leaking events. CHECK_GE(ret, 0) << "AsyncIO: io_getevents failed with error " << errnoStr(-ret); count += ret; } while (count < minRequests); DCHECK_LE(count, maxRequests); completed_.clear(); if (count == 0) { return folly::Range<Op**>(); } for (size_t i = 0; i < count; ++i) { DCHECK(events[i].obj); Op* op = boost::intrusive::get_parent_from_member( events[i].obj, &AsyncIOOp::iocb_); decrementPending(); op->complete(events[i].res); completed_.push_back(op); } return folly::Range<Op**>(&completed_.front(), count); }
// helper method for case where needles.size() <= 16 size_t qfind_first_byte_of_needles16(const StringPieceLite haystack, const StringPieceLite needles) { DCHECK_GT(haystack.size(), 0u); DCHECK_GT(needles.size(), 0u); DCHECK_LE(needles.size(), 16u); if ((needles.size() <= 2 && haystack.size() >= 256) || // must bail if we can't even SSE-load a single segment of haystack (haystack.size() < 16 && page_for(haystack.end() - 1) != page_for(haystack.data() + 15)) || // can't load needles into SSE register if it could cross page boundary page_for(needles.end() - 1) != page_for(needles.data() + 15)) { return detail::qfind_first_byte_of_nosse(haystack, needles); } auto arr2 = _mm_loadu_si128( reinterpret_cast<const __m128i*>(needles.data())); // do an unaligned load for first block of haystack auto arr1 = _mm_loadu_si128( reinterpret_cast<const __m128i*>(haystack.data())); auto index = _mm_cmpestri(arr2, int(needles.size()), arr1, int(haystack.size()), 0); if (index < 16) { return index; } // Now, we can do aligned loads hereafter... size_t i = nextAlignedIndex(haystack.data()); for (; i < haystack.size(); i+= 16) { arr1 = _mm_load_si128(reinterpret_cast<const __m128i*>(haystack.data() + i)); index = _mm_cmpestri( arr2, int(needles.size()), arr1, int(haystack.size() - i), 0); if (index < 16) { return i + index; } } return std::string::npos; }
void TruncateUTF8ToByteSize(const std::string& input, const size_t byte_size, std::string* output) { DCHECK(output); if (byte_size > input.length()) { *output = input; return; } DCHECK_LE(byte_size, static_cast<uint32>(kint32max)); // Note: This cast is necessary because CBU8_NEXT uses int32s. int32 truncation_length = static_cast<int32>(byte_size); int32 char_index = truncation_length - 1; const char* data = input.data(); // Using CBU8, we will move backwards from the truncation point // to the beginning of the string looking for a valid UTF8 // character. Once a full UTF8 character is found, we will // truncate the string to the end of that character. while (char_index >= 0) { int32 prev = char_index; base_icu::UChar32 code_point = 0; CBU8_NEXT(data, char_index, truncation_length, code_point); if (!IsValidCharacter(code_point) || !IsValidCodepoint(code_point)) { char_index = prev - 1; } else { break; } } if (char_index >= 0) *output = input.substr(0, char_index); else output->clear(); }
Decimal RangeInputType::findClosestTickMarkValue(const Decimal& value) { updateTickMarkValues(); if (!m_tickMarkValues.size()) return Decimal::nan(); size_t left = 0; size_t right = m_tickMarkValues.size(); size_t middle; while (true) { DCHECK_LE(left, right); middle = left + (right - left) / 2; if (!middle) break; if (middle == m_tickMarkValues.size() - 1 && m_tickMarkValues[middle] < value) { middle++; break; } if (m_tickMarkValues[middle - 1] <= value && m_tickMarkValues[middle] >= value) break; if (m_tickMarkValues[middle] < value) left = middle; else right = middle; } const Decimal closestLeft = middle ? m_tickMarkValues[middle - 1] : Decimal::infinity(Decimal::Negative); const Decimal closestRight = middle != m_tickMarkValues.size() ? m_tickMarkValues[middle] : Decimal::infinity(Decimal::Positive); if (closestRight - value < value - closestLeft) return closestRight; return closestLeft; }
inline bool contains(uint8_t i) const { DCHECK_LE(size_, 256); return sparse_[i] < size_ && dense_[sparse_[i]] == i; }
void serialize( ThriftTensor& out, LongRange sizes, LongRange strides, folly::IOBuf&& data, ThriftTensorDataType dtype, size_t elementSize, ThriftTensorEndianness endianness, SharingMode sharing) { DCHECK(!data.isChained()); if (endianness == ThriftTensorEndianness::NATIVE) { endianness = gMachineEndianness; } else { CHECK(endianness == gMachineEndianness) << "Non-native endianness not yet implemented"; } int ndims = sizes.size(); uint64_t dataSize = 1; uint64_t contiguousSize = 1; int firstContiguousDim = ndims - 1; if (!strides.empty()) { DCHECK_EQ(strides.size(), ndims); while (firstContiguousDim >= 0) { if (strides[firstContiguousDim] != contiguousSize) { break; } contiguousSize *= sizes[firstContiguousDim]; --firstContiguousDim; } ++firstContiguousDim; dataSize = contiguousSize; for (int i = 0; i < firstContiguousDim; ++i) { dataSize *= sizes[i]; } } else { for (auto s : sizes) { dataSize *= s; } contiguousSize = dataSize; firstContiguousDim = 0; } // Dimensions from firstContiguousDim till the last form a contiguous range // of contiguousSize elements; we'll copy / clone that in one go rather // than iterating through all elements. // We want bytes. dataSize *= elementSize; contiguousSize *= elementSize; DCHECK_LE(contiguousSize, dataSize); out.dataType = dtype; out.endianness = endianness; out.sizes.assign(sizes.begin(), sizes.end()); if (ndims == 0) { // Empty tensor, nothing to do. out.data = folly::IOBuf(); data = folly::IOBuf(); return; } if (firstContiguousDim == 0) { // We're done. DCHECK_GE(data.length(), dataSize); data.trimEnd(data.length() - dataSize); detail::applySharingMode(data, sharing); out.data = std::move(data); return; } // We have to do this the hard way... folly::IOBufQueue outQueue; // If the contiguous chunk size is >= kMinCloneSize, we clone rather // than copying static constexpr uint64_t kMinCloneSize = 4 << 10; // Don't allocate huge contiguous buffers. // jemalloc defers to mmap() for buffers of 4MiB or more. static constexpr uint64_t kMaxBlockSize = 2 << 20; folly::io::QueueAppender appender(&outQueue, std::min(dataSize, kMaxBlockSize)); std::vector<uint64_t> counter; counter.resize(firstContiguousDim); int idx = firstContiguousDim; const uint8_t* src = data.data(); bool mayShare = false; switch (sharing) { case SHARE_NONE: break; case SHARE_IOBUF_MANAGED: mayShare = data.isManagedOne(); break; case SHARE_ALL: mayShare = true; break; }; while (idx >= 0) { if (idx == firstContiguousDim) { if (mayShare && contiguousSize >= kMinCloneSize) { appender.insert(partialCloneOne(data, src - data.data(), contiguousSize)); } else { appender.push(src, contiguousSize); } --idx; continue; } src += strides[idx] * elementSize; if (++counter[idx] == sizes[idx]) { src -= sizes[idx] * strides[idx] * elementSize; counter[idx] = 0; --idx; } else { idx = firstContiguousDim; } } outQueue.move()->cloneInto(out.data); }