proxygen
IOBufUtil.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #pragma once
10 
11 #include <folly/Range.h>
12 #include <folly/io/Cursor.h>
13 #include <folly/io/IOBuf.h>
14 #include <algorithm>
15 
16 namespace fizz {
17 
23 
28 
37 template <typename Func>
38 void transformBuffer(const folly::IOBuf& in, folly::IOBuf& out, Func func) {
39  folly::IOBuf* currentOut = &out;
40  size_t offset = 0;
41 
42  for (auto current : in) {
43  size_t currentLength = current.size();
44 
45  while (currentLength != 0) {
46  size_t selected = std::min(
47  static_cast<size_t>(currentOut->length() - offset), currentLength);
48  func(
49  currentOut->writableData() + offset,
50  current.data() + (current.size() - currentLength),
51  selected);
52  currentLength -= selected;
53  offset += selected;
54  if (offset == currentOut->length()) {
55  offset = 0;
56  currentOut = currentOut->next();
57  }
58  }
59  }
60 }
61 
73 template <size_t BlockSize, typename Func>
76  size_t internallyBuffered = 0;
78  folly::io::Cursor input(&in);
79 
80  // block to handle writes along output buffer boundaries
81  std::array<uint8_t, BlockSize> blockBuffer = {};
82 
83  // ensure buffers are fine
84  while (!input.isAtEnd()) {
85  auto inputRange = input.peekBytes();
86  auto inputLen = inputRange.size();
87  auto outputLen = output.peekBytes().size();
88  if (inputLen + internallyBuffered < BlockSize) {
89  // input doesn't have enough - we can call func and it should
90  // internally buffer.
91  // This should be safe to just internally buffer since we took into
92  // account what was existing in the internal buffer already
93  auto numWritten = func(blockBuffer.data(), inputRange.data(), inputLen);
94  DCHECK_EQ(numWritten, 0) << "expected buffering. wrote " << numWritten;
95  // only update input offsets
96  internallyBuffered += inputLen;
97  input.skip(inputLen);
98  } else if (outputLen < BlockSize) {
99  // we have at least a block to write from input + internal buffer, so
100  // output didn't have enough room in this case
101  // copy a block from input in temp and then push onto output
102  auto numWritten = func(
103  blockBuffer.data(),
104  inputRange.data(),
105  // only provide it the amount needed for one block
106  BlockSize - internallyBuffered);
107  DCHECK_EQ(numWritten, BlockSize)
108  << "did not write full block bs=" << BlockSize
109  << " wrote=" << numWritten;
110 
111  // push the block onto output
112  output.push(blockBuffer.data(), BlockSize);
113 
114  // advance input
115  input.skip(BlockSize - internallyBuffered);
116  internallyBuffered = 0;
117  } else {
118  // we have at least one block that can be written from input to output
119  // calculate shared bytes while taking into account internal buffer
120  auto numSharedBytes = std::min(outputLen, inputLen + internallyBuffered);
121 
122  // this is the number we can safely (and expect) to write to output
123  auto numBlockBytes = numSharedBytes - (numSharedBytes % BlockSize);
124 
125  // try to grab as much from input - we can grab up to BlockSize - 1 more
126  auto maxToTake = (numBlockBytes - internallyBuffered) + (BlockSize - 1);
127  auto numToTake = std::min(inputLen, maxToTake);
128  auto numWritten =
129  func(output.writableData(), inputRange.data(), numToTake);
130 
131  DCHECK_EQ(numWritten, numBlockBytes);
132 
133  // advance cursors
134  input.skip(numToTake);
135  output.skip(numWritten);
136  // recalculate internal buffer state
137  internallyBuffered = (internallyBuffered + numToTake) % BlockSize;
138  }
139  }
140  return output;
141 }
142 } // namespace fizz
void trimBytes(IOBuf &buf, folly::MutableByteRange trimmed)
Definition: IOBufUtil.cpp:15
constexpr size_type size() const
Definition: Range.h:431
void push(const uint8_t *buf, size_t len)
Definition: Cursor.h:755
int current
Function< void()> Func
Definition: Executor.h:27
void XOR(ByteRange first, MutableByteRange second)
Definition: IOBufUtil.cpp:33
LogLevel min
Definition: LogLevel.cpp:30
uint8_t * writableData()
Definition: IOBuf.h:509
uint8_t * writableData()
Definition: Cursor.h:934
std::size_t length() const
Definition: IOBuf.h:533
folly::io::RWPrivateCursor transformBufferBlocks(const folly::IOBuf &in, folly::IOBuf &out, Func func)
Definition: IOBufUtil.h:75
void transformBuffer(const folly::IOBuf &in, folly::IOBuf &out, Func func)
Definition: IOBufUtil.h:38
Definition: Actions.h:16
IOBuf * next()
Definition: IOBuf.h:600
void skip(size_t len)
Definition: Cursor.h:371
constexpr detail::First first
Definition: Base-inl.h:2553