tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MemoryBuffer.cpp (3772B)


      1 //
      2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 #include "common/MemoryBuffer.h"
      8 
      9 #include <algorithm>
     10 #include <cstdlib>
     11 
     12 #include "common/debug.h"
     13 
     14 namespace angle
     15 {
     16 
     17 // MemoryBuffer implementation.
     18 MemoryBuffer::~MemoryBuffer()
     19 {
     20    if (mData)
     21    {
     22        free(mData);
     23        mData = nullptr;
     24    }
     25 }
     26 
     27 bool MemoryBuffer::resize(size_t size)
     28 {
     29    if (size == 0)
     30    {
     31        if (mData)
     32        {
     33            free(mData);
     34            mData = nullptr;
     35        }
     36        mSize = 0;
     37        return true;
     38    }
     39 
     40    if (size == mSize)
     41    {
     42        return true;
     43    }
     44 
     45    // Only reallocate if the size has changed.
     46    uint8_t *newMemory = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
     47    if (newMemory == nullptr)
     48    {
     49        return false;
     50    }
     51 
     52    if (mData)
     53    {
     54        // Copy the intersection of the old data and the new data
     55        std::copy(mData, mData + std::min(mSize, size), newMemory);
     56        free(mData);
     57    }
     58 
     59    mData = newMemory;
     60    mSize = size;
     61 
     62    return true;
     63 }
     64 
     65 void MemoryBuffer::fill(uint8_t datum)
     66 {
     67    if (!empty())
     68    {
     69        std::fill(mData, mData + mSize, datum);
     70    }
     71 }
     72 
     73 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
     74 {
     75    *this = std::move(other);
     76 }
     77 
     78 MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
     79 {
     80    std::swap(mSize, other.mSize);
     81    std::swap(mData, other.mData);
     82    return *this;
     83 }
     84 
     85 namespace
     86 {
     87 static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
     88 
     89 }  // anonymous namespace
     90 
     91 // ScratchBuffer implementation.
     92 ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
     93 
     94 ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
     95 
     96 ScratchBuffer::~ScratchBuffer() {}
     97 
     98 ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
     99 {
    100    *this = std::move(other);
    101 }
    102 
    103 ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
    104 {
    105    std::swap(mLifetime, other.mLifetime);
    106    std::swap(mResetCounter, other.mResetCounter);
    107    std::swap(mScratchMemory, other.mScratchMemory);
    108    return *this;
    109 }
    110 
    111 bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
    112 {
    113    return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
    114 }
    115 
    116 bool ScratchBuffer::getInitialized(size_t requestedSize,
    117                                   MemoryBuffer **memoryBufferOut,
    118                                   uint8_t initValue)
    119 {
    120    return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
    121 }
    122 
    123 bool ScratchBuffer::getImpl(size_t requestedSize,
    124                            MemoryBuffer **memoryBufferOut,
    125                            Optional<uint8_t> initValue)
    126 {
    127    if (mScratchMemory.size() == requestedSize)
    128    {
    129        mResetCounter    = mLifetime;
    130        *memoryBufferOut = &mScratchMemory;
    131        return true;
    132    }
    133 
    134    if (mScratchMemory.size() > requestedSize)
    135    {
    136        tick();
    137    }
    138 
    139    if (mScratchMemory.size() < requestedSize)
    140    {
    141        if (!mScratchMemory.resize(requestedSize))
    142        {
    143            return false;
    144        }
    145        mResetCounter = mLifetime;
    146        if (initValue.valid())
    147        {
    148            mScratchMemory.fill(initValue.value());
    149        }
    150    }
    151 
    152    ASSERT(mScratchMemory.size() >= requestedSize);
    153 
    154    *memoryBufferOut = &mScratchMemory;
    155    return true;
    156 }
    157 
    158 void ScratchBuffer::tick()
    159 {
    160    if (mResetCounter > 0)
    161    {
    162        --mResetCounter;
    163        if (mResetCounter == 0)
    164        {
    165            clear();
    166        }
    167    }
    168 }
    169 
    170 void ScratchBuffer::clear()
    171 {
    172    mResetCounter = mLifetime;
    173    if (mScratchMemory.size() > 0)
    174    {
    175        mScratchMemory.clear();
    176    }
    177 }
    178 
    179 }  // namespace angle