17ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Copyright 2014 The Android Open Source Project
27ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//
37ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// This software is licensed under the terms of the GNU General Public
47ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// License version 2, as published by the Free Software Foundation, and
57ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// may be copied, distributed, and modified under those terms.
67ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//
77ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// This program is distributed in the hope that it will be useful,
87ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// but WITHOUT ANY WARRANTY; without even the implied warranty of
97ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// GNU General Public License for more details.
117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#ifndef ANDROID_BASE_SCOPED_STDIO_FILE_H
137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#define ANDROID_BASE_SCOPED_STDIO_FILE_H
147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include <stdio.h>
167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmannamespace android {
187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmannamespace base {
197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Helper class used to implement a scoped stdio FILE* pointer.
217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// I.e. guarantees that the file is closed on scope exit, unless
227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// the release() method is called. It is also possible to close
237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// the file explicitly with close().
247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanclass ScopedStdioFile {
257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanpublic:
267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Default constructor, uses an empty file.
277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    ScopedStdioFile() : mFile(NULL) {}
287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Regular constructor, takes owneship of |file|.
307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    explicit ScopedStdioFile(FILE* file) : mFile(file) {}
317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Destructor always calls close().
337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    ~ScopedStdioFile() { close(); }
347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Returns FILE* pointer directly.
367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    FILE* get() const { return mFile; }
377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Release the FILE* handle and return it to the caller, which becomes
397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // its owner. Returns NULL if the instance was already closed or empty.
407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    FILE* release() {
417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        FILE* file = mFile;
427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        mFile = NULL;
437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        return file;
447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    }
457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Swap two scoped FILE* pointers.
477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    void swap(ScopedStdioFile* other) {
487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        FILE* tmp = other->mFile;
497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        other->mFile = mFile;
507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        mFile = tmp;
517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    }
527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // Explicit close of a scoped FILE*.
547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    void close() {
5557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer        if (mFile) {
5657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer            ::fclose(mFile);
577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            mFile = NULL;
587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        }
597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    }
607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanprivate:
617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    FILE* mFile;
627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman};
637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}  // namespace base
657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}  // namespace android
667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer#endif  // ANDROID_BASE_SCOPED_STDIO_FILE_H
6857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer