scoped_file.h 2.75 KB
Newer Older
gejun's avatar
gejun committed
1 2 3 4
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef BUTIL_FILES_SCOPED_FILE_H_
#define BUTIL_FILES_SCOPED_FILE_H_
gejun's avatar
gejun committed
7 8 9

#include <stdio.h>

10 11 12 13 14
#include "butil/base_export.h"
#include "butil/logging.h"
#include "butil/memory/scoped_ptr.h"
#include "butil/scoped_generic.h"
#include "butil/build_config.h"
gejun's avatar
gejun committed
15

16
namespace butil {
gejun's avatar
gejun committed
17 18 19 20

namespace internal {

#if defined(OS_POSIX)
21
struct BUTIL_EXPORT ScopedFDCloseTraits {
gejun's avatar
gejun committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
  static int InvalidValue() {
    return -1;
  }
  static void Free(int fd);
};
#endif

}  // namespace internal

// -----------------------------------------------------------------------------

#if defined(OS_POSIX)
// A low-level Posix file descriptor closer class. Use this when writing
// platform-specific code, especially that does non-file-like things with the
// FD (like sockets).
//
38
// If you're writing low-level Windows code, see butil/win/scoped_handle.h
gejun's avatar
gejun committed
39 40 41
// which provides some additional functionality.
//
// If you're writing cross-platform code that deals with actual files, you
42
// should generally use butil::File instead which can be constructed with a
gejun's avatar
gejun committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
// handle, and in addition to handling ownership, has convenient cross-platform
// file manipulation functions on it.
typedef ScopedGeneric<int, internal::ScopedFDCloseTraits> ScopedFD;
#endif

//// Automatically closes |FILE*|s.
class ScopedFILE {
    MOVE_ONLY_TYPE_FOR_CPP_03(ScopedFILE, RValue);
public:
    ScopedFILE() : _fp(NULL) {}

    // Open file at |path| with |mode|.
    // If fopen failed, operator FILE* returns NULL and errno is set.
    ScopedFILE(const char *path, const char *mode) {
        _fp = fopen(path, mode);
    }

    // |fp| must be the return value of fopen as we use fclose in the
    // destructor, otherwise the behavior is undefined
    explicit ScopedFILE(FILE *fp) :_fp(fp) {}

    ScopedFILE(RValue rvalue) {
        _fp = rvalue.object->_fp;
        rvalue.object->_fp = NULL;
    }

    ~ScopedFILE() {
        if (_fp != NULL) {
            fclose(_fp);
            _fp = NULL;
        }
    }

    // Close current opened file and open another file at |path| with |mode|
    void reset(const char* path, const char* mode) {
        reset(fopen(path, mode));
    }

    void reset() { reset(NULL); }

    void reset(FILE *fp) {
        if (_fp != NULL) {
            fclose(_fp);
            _fp = NULL;
        }
        _fp = fp;
    }

    // Set internal FILE* to NULL and return previous value.
    FILE* release() {
        FILE* const prev_fp = _fp;
        _fp = NULL;
        return prev_fp;
    }
    
    operator FILE*() const { return _fp; }

    FILE* get() { return _fp; }
    
private:
    FILE* _fp;
};

106
}  // namespace butil
gejun's avatar
gejun committed
107

108
#endif  // BUTIL_FILES_SCOPED_FILE_H_