1890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// Copyright 2014 The Android Open Source Project
2890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner//
3890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// This software is licensed under the terms of the GNU General Public
4890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// License version 2, as published by the Free Software Foundation, and
5890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// may be copied, distributed, and modified under those terms.
6890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner//
7890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// This program is distributed in the hope that it will be useful,
8890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of
9890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// GNU General Public License for more details.
11890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
12890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner#ifndef ANDROID_BASE_SCOPED_STDIO_FILE_H
13890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner#define ANDROID_BASE_SCOPED_STDIO_FILE_H
14890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
15890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner#include <stdio.h>
16890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
17890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turnernamespace android {
18890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turnernamespace base {
19890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
20890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// Helper class used to implement a scoped stdio FILE* pointer.
21890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// I.e. guarantees that the file is closed on scope exit, unless
22890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// the release() method is called. It is also possible to close
23890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner// the file explicitly with close().
24890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turnerclass ScopedStdioFile {
25890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turnerpublic:
26890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Default constructor, uses an empty file.
27890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    ScopedStdioFile() : mFile(NULL) {}
28890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
29890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Regular constructor, takes owneship of |file|.
30890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    explicit ScopedStdioFile(FILE* file) : mFile(file) {}
31890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
32890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Destructor always calls close().
33890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    ~ScopedStdioFile() { close(); }
34890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
35890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Returns FILE* pointer directly.
36890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    FILE* get() const { return mFile; }
37890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
38890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Release the FILE* handle and return it to the caller, which becomes
39890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // its owner. Returns NULL if the instance was already closed or empty.
40890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    FILE* release() {
41890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        FILE* file = mFile;
42890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        mFile = NULL;
43890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        return file;
44890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    }
45890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
46890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Swap two scoped FILE* pointers.
47890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    void swap(ScopedStdioFile* other) {
48890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        FILE* tmp = other->mFile;
49890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        other->mFile = mFile;
50890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        mFile = tmp;
51890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    }
52890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
53890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    // Explicit close of a scoped FILE*.
54890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    void close() {
55890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        if (mFile) {
56890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner            ::fclose(mFile);
57890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner            mFile = NULL;
58890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner        }
59890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    }
60890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turnerprivate:
61890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner    FILE* mFile;
62890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner};
63890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
64890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner}  // namespace base
65890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner}  // namespace android
66890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner
67890f46464b0a35cbee882a5d62bd86a49879cabcDavid 'Digit' Turner#endif  // ANDROID_BASE_SCOPED_STDIO_FILE_H
68