Home | History | Annotate | Download | only in wifilogd
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef MESSAGE_BUFFER_H_
     18 #define MESSAGE_BUFFER_H_
     19 
     20 #include <cstdint>
     21 #include <memory>
     22 #include <tuple>
     23 
     24 #include "android-base/macros.h"
     25 
     26 #include "wifilogd/local_utils.h"
     27 
     28 namespace android {
     29 namespace wifilogd {
     30 
     31 // A fixed-size buffer, which provides FIFO access to read and write
     32 // a sequence of messages.
     33 class MessageBuffer {
     34  public:
     35   // A wrapper which guarantees that a MessageBuffer will be rewound,
     36   // when the program exits the wrapper's scope. The user must ensure that
     37   // |buffer| does not expire before the ScopedRewinder.
     38   class ScopedRewinder {
     39    public:
     40     explicit ScopedRewinder(NONNULL MessageBuffer* buffer) : buffer_(buffer) {}
     41     ~ScopedRewinder() { buffer_->Rewind(); }
     42 
     43    private:
     44     MessageBuffer* const buffer_;
     45   };
     46 
     47   // Constructs the buffer. |size| must be greater than GetHeaderSize().
     48   explicit MessageBuffer(size_t size);
     49 
     50   // Appends a single message to the buffer. |data_len| must be >=1. Returns
     51   // true if the message was added to the buffer.
     52   bool Append(NONNULL const uint8_t* data, uint16_t data_len);
     53 
     54   // Returns true if the buffer is large enough to hold |length| bytes of user
     55   // data, when the buffer is empty.
     56   bool CanFitEver(uint16_t length) const;
     57 
     58   // Returns true if the buffer currently has enough free space to hold |length|
     59   // bytes of user data.
     60   bool CanFitNow(uint16_t length) const;
     61 
     62   // Clears the buffer. An immediately following read operation will return an
     63   // empty message. An immediately following write operation will write to the
     64   // head of the buffer. Clearing may be lazy (i.e., underlying storage is not
     65   // necessarily zeroed).
     66   void Clear();
     67 
     68   // Returns the first unread message in the buffer. If there is no such
     69   // message, returns {nullptr, 0}. MessageBuffer retains ownership of the
     70   // message's storage.
     71   std::tuple<const uint8_t*, size_t> ConsumeNextMessage();
     72 
     73   // Returns the size of MessageBuffer's per-message header.
     74   static constexpr size_t GetHeaderSize() { return sizeof(LengthHeader); }
     75 
     76   // Returns the total available free space in the buffer. This may be
     77   // larger than the usable space, due to overheads.
     78   size_t GetFreeSize() const { return capacity_ - write_pos_; }
     79 
     80   // Resets the read pointer to the start of the buffer. An immediately
     81   // following read will return the first message in the buffer. An immediately
     82   // following write, however, will be placed at the same position as if
     83   // Rewind() had not been called.
     84   void Rewind();
     85 
     86  private:
     87   struct LengthHeader {
     88     uint16_t payload_len;
     89   };
     90 
     91   // Prepares a header, and writes that header into the buffer.
     92   void AppendHeader(uint16_t message_len);
     93 
     94   // Writes arbitrary data into the buffer.
     95   void AppendRawBytes(NONNULL const void* data_start, size_t data_len);
     96 
     97   // Returns the total number of bytes available for reading. This number
     98   // includes headers.
     99   size_t GetReadableSize() const { return write_pos_ - read_pos_; }
    100 
    101   const std::unique_ptr<uint8_t[]> data_;
    102   const size_t capacity_;
    103   size_t read_pos_;
    104   size_t write_pos_;
    105 
    106   // MessageBuffer is a value type, so it would be semantically reasonable to
    107   // support copy and assign. Performance-wise, though, we should avoid
    108   // copies. Remove the copy constructor and the assignment operator, to
    109   // ensure that we don't accidentally make copies.
    110   DISALLOW_COPY_AND_ASSIGN(MessageBuffer);
    111 };
    112 
    113 }  // namespace wifilogd
    114 }  // namespace android
    115 
    116 #endif  // MESSAGE_BUFFER_H_
    117