| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #ifndef CUTTLEFISH_COMMON_COMMON_LIBS_AUTO_RESOURCES_AUTO_RESOURCES_H_ |
| #define CUTTLEFISH_COMMON_COMMON_LIBS_AUTO_RESOURCES_AUTO_RESOURCES_H_ |
| |
| #include <stdarg.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <pthread.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| |
| template <typename T, size_t N> |
| char (&ArraySizeHelper(T (&array)[N]))[N]; |
| |
| template <typename T, size_t N> |
| char (&ArraySizeHelper(const T (&array)[N]))[N]; |
| |
| #define arraysize(array) (sizeof(ArraySizeHelper(array))) |
| |
| // Automatically close a file descriptor |
| class AutoCloseFILE { |
| public: |
| explicit AutoCloseFILE(FILE *f) : f_(f) { } |
| virtual ~AutoCloseFILE() { |
| if (f_) { |
| (void)::fclose(f_); |
| f_ = NULL; |
| } |
| } |
| |
| operator FILE*() const { |
| return f_; |
| } |
| |
| bool CopyFrom(const AutoCloseFILE& in); |
| |
| bool IsError() const { |
| return f_ == NULL; |
| } |
| |
| bool IsEOF() const { |
| return IsError() || feof(f_); |
| } |
| |
| bool IsOpen() const { |
| return f_ != NULL; |
| } |
| |
| // Close the underlying file descriptor, returning a status to give the caller |
| // the chance to act on failure to close. |
| // Returns true on success. |
| bool close() { |
| bool rval = true; |
| if (f_) { |
| rval = !::fclose(f_); |
| f_ = NULL; |
| } |
| return rval; |
| } |
| |
| private: |
| AutoCloseFILE& operator=(const AutoCloseFILE & o); |
| explicit AutoCloseFILE(const AutoCloseFILE &); |
| |
| FILE* f_; |
| }; |
| |
| // Automatically close a file descriptor |
| class AutoCloseFileDescriptor { |
| public: |
| explicit AutoCloseFileDescriptor(int fd) : fd_(fd) { } |
| virtual ~AutoCloseFileDescriptor() { |
| if (fd_ != -1) { |
| (void)::close(fd_); |
| fd_ = -1; |
| } |
| } |
| |
| operator int() const { |
| return fd_; |
| } |
| |
| bool IsError() const { |
| return fd_ == -1; |
| } |
| |
| // Close the underlying file descriptor, returning a status to give the caller |
| // the chance to act on failure to close. |
| // Returns true on success. |
| bool close() { |
| bool rval = true; |
| if (fd_ != -1) { |
| rval = !::close(fd_); |
| fd_ = -1; |
| } |
| return rval; |
| } |
| |
| private: |
| AutoCloseFileDescriptor& operator=(const AutoCloseFileDescriptor & o); |
| explicit AutoCloseFileDescriptor(const AutoCloseFileDescriptor &); |
| |
| int fd_; |
| }; |
| |
| // In C++11 this is just std::vector<char>, but Android isn't |
| // there yet. |
| class AutoFreeBuffer { |
| public: |
| enum { |
| // Minimum reserve size of AutoFreeBuffer to consider shrinking reservation. |
| // Any buffer shorter than this will not be shrunk. |
| kAutoBufferShrinkReserveThreshold = 8192 |
| }; |
| |
| AutoFreeBuffer() |
| : data_(NULL), size_(0), reserve_size_(0) {} |
| |
| AutoFreeBuffer(size_t reserve_size) |
| : data_(NULL), size_(0), reserve_size_(0) { |
| Reserve(reserve_size); |
| } |
| |
| ~AutoFreeBuffer(); |
| void Clear(); |
| bool Resize(size_t newsize); |
| bool Reserve(size_t newsize); |
| bool SetToString(const char* in); |
| bool Append(const void* new_data, size_t new_data_size); |
| size_t PrintF(const char* format, ... ); |
| |
| char* data() { |
| return data_; |
| } |
| |
| const char* data() const { |
| return data_; |
| } |
| |
| char* begin() { |
| return data_; |
| } |
| |
| const char* begin() const { |
| return data_; |
| } |
| |
| char* end() { |
| return data_ + size_; |
| } |
| |
| const char* end() const { |
| return data_ + size_; |
| } |
| |
| size_t size() const { |
| return size_; |
| } |
| |
| size_t reserve_size() const { |
| return reserve_size_; |
| } |
| |
| void Swap(AutoFreeBuffer& other) { |
| char* temp_ptr = data_; |
| data_ = other.data_; |
| other.data_ = temp_ptr; |
| |
| size_t temp_size = size_; |
| size_ = other.size_; |
| other.size_ = temp_size; |
| |
| temp_size = reserve_size_; |
| reserve_size_ = other.reserve_size_; |
| other.reserve_size_ = temp_size; |
| } |
| |
| bool operator==(const AutoFreeBuffer& other) const { |
| return (size_ == other.size_) && !memcmp(data_, other.data_, size_); |
| } |
| |
| bool operator!=(const AutoFreeBuffer& other) const { |
| return !(*this == other); |
| } |
| |
| protected: |
| char *data_; |
| size_t size_; |
| size_t reserve_size_; |
| |
| private: |
| AutoFreeBuffer& operator=(const AutoFreeBuffer&); |
| explicit AutoFreeBuffer(const AutoFreeBuffer&); |
| }; |
| |
| class AutoUMask { |
| public: |
| explicit AutoUMask(mode_t mask) { |
| prev_umask = umask(mask); |
| } |
| |
| ~AutoUMask() { |
| umask(prev_umask); |
| } |
| private: |
| mode_t prev_umask; |
| }; |
| #endif // CUTTLEFISH_COMMON_COMMON_LIBS_AUTO_RESOURCES_AUTO_RESOURCES_H_ |