• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CopyFrom(const AutoCloseFILE & in)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 
~AutoFreeBuffer()45 AutoFreeBuffer::~AutoFreeBuffer() {
46   if (data_) free(data_);
47 }
48 
Clear()49 void AutoFreeBuffer::Clear() {
50   size_ = 0;
51 }
52 
Reserve(size_t newsize)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 
Resize(size_t newsize)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 
SetToString(const char * in)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 
Append(const void * new_data,size_t new_data_size)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 
PrintF(const char * format,...)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