1 /** @file
2 
3     Buffer Writer for an MIOBuffer.
4 
5     @section license License
6 
7     Licensed to the Apache Software Foundation (ASF) under one
8     or more contributor license agreements.  See the NOTICE file
9     distributed with this work for additional information
10     regarding copyright ownership.  The ASF licenses this file
11     to you under the Apache License, Version 2.0 (the
12     "License"); you may not use this file except in compliance
13     with the License.  You may obtain a copy of the License at
14 
15     http://www.apache.org/licenses/LICENSE-2.0
16 
17     Unless required by applicable law or agreed to in writing, software
18     distributed under the License is distributed on an "AS IS" BASIS,
19     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20     See the License for the specific language governing permissions and
21     limitations under the License.
22  */
23 
24 #pragma once
25 
26 #include <cstring>
27 #include <iosfwd>
28 
29 #include "tscore/ink_assert.h"
30 #include "tscore/BufferWriter.h"
31 
32 #if !defined(UNIT_TEST_BUFFER_WRITER)
33 #include <I_IOBuffer.h>
34 #endif
35 
36 /** BufferWriter interface on top of IOBuffer blocks.
37 
38     @internal This should be changed to IOBufferChain once I port that to open source.
39  */
40 class MIOBufferWriter : public ts::BufferWriter
41 {
42   using self_type = MIOBufferWriter; ///< Self reference type.
43 
44 public:
45   explicit MIOBufferWriter(MIOBuffer *miob) : _miob(miob) {}
46 
47   self_type &write(const void *data_, size_t length) override;
48 
49   self_type &
50   write(char c) override
51   {
52     return this->write(&c, 1);
53   }
54 
55   bool
56   error() const override
57   {
58     return false;
59   }
60 
61   char *
62   auxBuffer() override
63   {
64     IOBufferBlock *iobbPtr = _miob->first_write_block();
65 
66     if (!iobbPtr) {
67       return nullptr;
68     }
69 
70     return iobbPtr->end();
71   }
72 
73   size_t
74   auxBufferCapacity() const
75   {
76     IOBufferBlock *iobbPtr = _miob->first_write_block();
77 
78     if (!iobbPtr) {
79       return 0;
80     }
81 
82     return iobbPtr->write_avail();
83   }
84 
85   // Write the first n characters that have been placed in the auxiliary buffer.  This call invalidates the auxiliary buffer.
86   // This function should not be called if no auxiliary buffer is available.
87   //
88   self_type &
89   fill(size_t n) override
90   {
91     if (n) {
92       IOBufferBlock *iobbPtr = _miob->first_write_block();
93 
94       ink_assert(iobbPtr and (n <= size_t(iobbPtr->write_avail())));
95 
96       iobbPtr->fill(n);
97 
98       _numWritten += n;
99     }
100 
101     return *this;
102   }
103 
104   // No fixed limit on capacity.
105   //
106   size_t
107   capacity() const override
108   {
109     return (~size_t(0));
110   }
111 
112   size_t
113   extent() const override
114   {
115     return _numWritten;
116   }
117 
118   // Not useful in this derived class.
119   //
120   self_type &clip(size_t) override { return *this; }
121 
122   // Not useful in this derived class.
123   //
124   self_type &extend(size_t) override { return *this; }
125 
126   // This must not be called for this derived class.
127   //
128   const char *
129   data() const override
130   {
131     ink_assert(false);
132     return nullptr;
133   }
134 
135   /// Output the buffer contents to the @a stream.
136   /// @return The destination stream.
137   std::ostream &operator>>(std::ostream &stream) const override;
138   /// Output the buffer contents to the file for file descriptor @a fd.
139   /// @return The number of bytes written.
140   ssize_t operator>>(int fd) const override;
141 
142 protected:
143   MIOBuffer *_miob;
144 
145 private:
146   size_t _numWritten = 0;
147 
148   virtual void
149   addBlock()
150   {
151     _miob->add_block();
152   }
153   // INTERNAL - Overload removed, make sure it's not used.
154   self_type &write(size_t n);
155 };
156