HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Base64EncodeFilter.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_Base64EncodeFilter.h ( UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_Base64EncodeFilter__
12 #define __UT_Base64EncodeFilter__
13 
14 #include "UT_API.h"
15 #include "UT_Base64.h"
16 
17 #include <UT/UT_WorkBuffer.h>
18 #include <UT/UT_UniquePtr.h>
19 #include <SYS/SYS_Types.h>
20 #include <SYS/SYS_BoostStreams.h>
21 
22 /// A boost multicharacter output filter, used to base64 encode an output
23 /// data stream.
24 ///
25 /// NB: This filter does not support a non-blocking Sink, expecting all write
26 /// requests to consume all the characters requested.
27 class UT_API UT_Base64EncodeFilter : public bios::multichar_output_filter
28 {
29 public:
30  typedef char char_type;
31 
32  explicit UT_Base64EncodeFilter() : myPendingBlockSize(0) {}
33  ~UT_Base64EncodeFilter() = default;
34 
35  // DANGER: Boost will copy this class around a few times before the
36  // first call to write(). We assume that if we're copied again after
37  // that, its use will be restarted.
39  : myPendingBlockSize(0) {}
41  {
42  if (this != &copy)
43  myPendingBlockSize = 0;
44  return *this;
45  }
46 
47  template<typename Sink>
48  std::streamsize write(Sink& dest, const char* source_buffer,
49  std::streamsize source_buffer_size);
50 
51  template<typename Sink>
52  void close(Sink& dest);
53 private:
54  UT_WorkBuffer & initEncodeBuffer()
55  {
56  if (!myEncodeBuffer)
57  myEncodeBuffer = UTmakeUnique<UT_WorkBuffer>();
58  else
59  myEncodeBuffer->clear();
60  return *myEncodeBuffer.get();
61  }
62 
63  uint8 myPendingBlock[3];
64  int myPendingBlockSize;
65  UT_UniquePtr<UT_WorkBuffer> myEncodeBuffer;
66 };
67 
68 
69 template <typename Sink>
70 inline std::streamsize
72  Sink& dest,
73  const char* source_buffer,
74  std::streamsize source_buffer_size)
75 {
76  // This filter only supports blocking Sinks, and so always consumes the
77  // full input.
78  std::streamsize consumed_size = source_buffer_size;
79 
80  // We process the source in blocks of 3 characters, starting with any
81  // leftovers from a previous write call. A leftover partial block is
82  // deferred until the next write() or close().
83  if (myPendingBlockSize > 0)
84  {
85  while (myPendingBlockSize < 3 && source_buffer_size)
86  {
87  myPendingBlock[myPendingBlockSize++] =
88  *reinterpret_cast<const uint8 *>(source_buffer++);
89  source_buffer_size--;
90  }
91  if (myPendingBlockSize == 3)
92  {
93  UT_WorkBuffer &output = initEncodeBuffer();
94  UT_Base64::encode(myPendingBlock, 3, output);
95  // NB: Assumes blocking Sink.
96  bios::write<Sink>(dest, output.buffer(), output.length());
97  myPendingBlockSize = 0;
98  }
99  }
100 
101  if (source_buffer_size >= 3)
102  {
103  UT_WorkBuffer &output = initEncodeBuffer();
104  std::streamsize remainder = source_buffer_size % 3;
105  // Process all remaining full blocks of 3 bytes in the source.
106  UT_Base64::encode(reinterpret_cast<const uint8 *>(source_buffer),
107  source_buffer_size - remainder, output);
108  // NB: Assumes blocking Sink.
109  bios::write<Sink>(dest, output.buffer(), output.length());
110  source_buffer += (source_buffer_size - remainder);
111  source_buffer_size = remainder;
112  }
113 
114  // Defer any extra input characters until we can process them as part of a
115  // full block or have to output them as a partial block with padding.
116  if (source_buffer_size > 0)
117  {
118  for (int i = 0; i < source_buffer_size; i++)
119  myPendingBlock[i] = source_buffer[i];
120  myPendingBlockSize = source_buffer_size;
121  }
122 
123  return consumed_size;
124 }
125 
126 template<typename Sink>
127 inline void
129 {
130  // Encode the final partial block, if any.
131  if (myPendingBlockSize > 0)
132  {
133  UT_WorkBuffer &output = initEncodeBuffer();
134 
135  UT_Base64::encode(myPendingBlock, myPendingBlockSize, output);
136  // NB: Assumes blocking Sink.
137  bios::write<Sink>(dest, output.buffer(), output.length());
138  myPendingBlockSize = 0;
139  }
140 }
141 
142 #endif // __UT_Base64EncodeFilter__
143 
SYS_FORCE_INLINE exint length() const
UT_Base64EncodeFilter & operator=(const UT_Base64EncodeFilter &copy)
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
UT_Base64EncodeFilter(const UT_Base64EncodeFilter &copy)
SYS_FORCE_INLINE const char * buffer() const
#define UT_API
Definition: UT_API.h:14
void close() override
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
unsigned char uint8
Definition: SYS_Types.h:36
static void encode(const UT_WorkBuffer &src, UT_WorkBuffer &dst)
std::streamsize write(Sink &dest, const char *source_buffer, std::streamsize source_buffer_size)
SYS_FORCE_INLINE void clear()