diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2019-10-28 14:21:27 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2020-03-25 19:05:17 -0400 | 
| commit | 9f446be76ee804bcd2f6ff8546612c9fcaf2a73e (patch) | |
| tree | d0f3ab27ac198681c69ee37783ddd54358dda1ca /indra/llcommon | |
| parent | cc6f1d6195c457dc744ff23ac06ccd3a2d948aca (diff) | |
DRTVWR-476: Add LLUniqueFile, adding RAII semantics to LLFILE*.
LLUniqueFile wraps an LLFILE* in a move-only class that closes the wrapped
LLFILE* on destruction. It provides conversion operators to permit idiomatic
usage as an LLFILE* value.
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/llfile.h | 63 | 
1 files changed, 63 insertions, 0 deletions
| diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 398938b729..9de095b45d 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -86,6 +86,69 @@ public:  	static  const char * tmpdir();  }; +/// RAII class +class LLUniqueFile +{ +public: +    // empty +    LLUniqueFile(): mFileHandle(nullptr) {} +    // wrap (e.g.) result of LLFile::fopen() +    LLUniqueFile(LLFILE* f): mFileHandle(f) {} +    // no copy +    LLUniqueFile(const LLUniqueFile&) = delete; +    // move construction +    LLUniqueFile(LLUniqueFile&& other) +    { +        mFileHandle = other.mFileHandle; +        other.mFileHandle = nullptr; +    } +    // The point of LLUniqueFile is to close on destruction. +    ~LLUniqueFile() +    { +        close(); +    } + +    // simple assignment +    LLUniqueFile& operator=(LLFILE* f) +    { +        close(); +        mFileHandle = f; +        return *this; +    } +    // copy assignment deleted +    LLUniqueFile& operator=(const LLUniqueFile&) = delete; +    // move assignment +    LLUniqueFile& operator=(LLUniqueFile&& other) +    { +        close(); +        std::swap(mFileHandle, other.mFileHandle); +        return *this; +    } + +    // explicit close operation +    void close() +    { +        if (mFileHandle) +        { +            // in case close() throws, set mFileHandle null FIRST +            LLFILE* h{nullptr}; +            std::swap(h, mFileHandle); +            LLFile::close(h); +        } +    } + +    // detect whether the wrapped LLFILE is open or not +    explicit operator bool() const { return bool(mFileHandle); } +    bool operator!() { return ! mFileHandle; } + +    // LLUniqueFile should be usable for any operation that accepts LLFILE* +    // (or FILE* for that matter) +    operator LLFILE*() const { return mFileHandle; } + +private: +    LLFILE* mFileHandle; +}; +  #if LL_WINDOWS  /**   *  @brief  Controlling input for files. | 
