Home | History | Annotate | Download | only in auto_resources
      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 #include "common/libs/auto_resources/auto_resources.h"
     17 
     18 #include <errno.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 bool AutoCloseFILE::CopyFrom(const AutoCloseFILE& in) {
     23   char buffer[8192];
     24   while (!in.IsEOF()) {
     25     size_t num_read = fread(buffer, 1, sizeof(buffer), in);
     26     if (!num_read) {
     27       if (in.IsEOF()) {
     28         return true;
     29       }
     30       printf("%s: unable to fread %s:%d (%s)\n",
     31              __FUNCTION__, __FILE__, __LINE__, strerror(errno));
     32       return false;
     33     }
     34     size_t num_written = fwrite(buffer, 1, num_read, *this);
     35     if (num_written != num_read) {
     36       printf("%s: unable to fwrite, %zu != %zu %s:%d (%s)\n",
     37              __FUNCTION__, num_read, num_written, __FILE__, __LINE__,
     38              strerror(errno));
     39       return false;
     40     }
     41   }
     42   return true;
     43 }
     44 
     45 AutoFreeBuffer::~AutoFreeBuffer() {
     46   if (data_) free(data_);
     47 }
     48 
     49 void AutoFreeBuffer::Clear() {
     50   size_ = 0;
     51 }
     52 
     53 bool AutoFreeBuffer::Reserve(size_t newsize) {
     54   if (newsize > reserve_size_ ||
     55       reserve_size_ > kAutoBufferShrinkReserveThreshold) {
     56     char* newdata = static_cast<char*>(realloc(data_, newsize));
     57     // If realloc fails, everything remains unchanged.
     58     if (!newdata && newsize) return false;
     59 
     60     reserve_size_ = newsize;
     61     data_ = newdata;
     62   }
     63   if (size_ > newsize) size_ = newsize;
     64   return true;
     65 }
     66 
     67 bool AutoFreeBuffer::Resize(size_t newsize) {
     68   // If reservation is small, and we get a shrink request, simply reduce size_.
     69   if (reserve_size_ < kAutoBufferShrinkReserveThreshold && newsize < size_) {
     70     size_ = newsize;
     71     return true;
     72   }
     73 
     74   if (!Reserve(newsize)) return false;
     75 
     76   // Should we keep this? Sounds like it should be called Grow().
     77   if (newsize > size_) memset(&data_[size_], 0, newsize - size_);
     78   size_ = newsize;
     79   return true;
     80 }
     81 
     82 bool AutoFreeBuffer::SetToString(const char* in) {
     83   size_t newsz = strlen(in) + 1;
     84   if (!Resize(newsz)) return false;
     85   memcpy(data_, in, newsz);
     86   return true;
     87 }
     88 
     89 bool AutoFreeBuffer::Append(const void* new_data, size_t new_data_size) {
     90   size_t offset = size_;
     91   if (!Resize(offset + new_data_size)) return false;
     92   memcpy(&data_[offset], new_data, new_data_size);
     93   return true;
     94 }
     95 
     96 size_t AutoFreeBuffer::PrintF(const char* format, ... ) {
     97   va_list args;
     98 
     99   // Optimize: Use whatever reservation left we have for initial printf.
    100   // If reservation is not long enough, resize and try again.
    101 
    102   va_start(args, format);
    103   size_t printf_size = vsnprintf(data_, reserve_size_, format, args);
    104   va_end(args);
    105 
    106   // vsnprintf write no more than |reserve_size_| bytes including trailing \0.
    107   // Result value equal or greater than |reserve_size_| signals truncated
    108   // output.
    109   if (printf_size < reserve_size_) {
    110     size_ = printf_size + 1;
    111     return printf_size;
    112   }
    113 
    114   // Grow buffer and re-try printf.
    115   if (!Resize(printf_size + 1)) return 0;
    116   va_start(args, format);
    117   vsprintf(data_, format, args);
    118   va_end(args);
    119   return printf_size;
    120 }
    121 
    122