Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/nsprpub/lib/prstreams/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  prstrms.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/*
 * Robin J. Maxwell 11-22-96
 * Fredrik Roubert <roubert@google.com> 2010-07-23
 * Matt Austern <austern@google.com> 2010-07-23
 */


#include "prstrms.h"

#include <cstdio>
#include <cstring>
#include <ios>
#include <new>

using std::ios_base;
using std::iostream;
using std::istream;
using std::nothrow;
using std::ostream;
using std::streambuf;
using std::streamsize;


PRfilebuf::PRfilebuf():
    _fd(NULL),
    _opened(false),
    _allocated(false),
    _unbuffered(false),
    _user_buf(false),
    _buf_base(NULL),
    _buf_end(NULL) { }


PRfilebuf::PRfilebuf(PRFileDesc *fd):
    _fd(fd),
    _opened(false),
    _allocated(false),
    _unbuffered(false),
    _user_buf(false),
    _buf_base(NULL),
    _buf_end(NULL) { }


PRfilebuf::PRfilebuf(PRFileDesc *fd, char_type *ptr, streamsize len):
    _fd(fd),
    _opened(false),
    _allocated(false),
    _unbuffered(false),
    _user_buf(false),
    _buf_base(NULL),
    _buf_end(NULL)
{
    setbuf(ptr, len);
}


PRfilebuf::~PRfilebuf()
{
    if (_opened) {
        close();
    } else {
        sync();
    }
    if (_allocated) {
        delete _buf_base;
    }
}


PRfilebuf *PRfilebuf::open(
    const char *name, ios_base::openmode flags, PRIntn mode)
{
    if (_fd != NULL) {
        return NULL;  // Error if already open.
    }

    // Translate flags argument.
    PRIntn prflags = 0;
    bool ate = (flags & ios_base::ate) != 0;
    flags &= ~(ios_base::ate | ios_base::binary);

    // TODO: The flag PR_CREATE_FILE should probably be used for the cases
    // (out), (out|app), (out|trunc) and (in|out|trunc) as the C++ standard
    // specifies that these cases should open files 'as if by using fopen with
    // "w"'. But adding that flag here will cause the unit test to leave files
    // behind after running (which might or might not be an error in the unit
    // test) so the matter needs further investigation before any changes are
    // made. The old prstreams implementation used the non-standard flag
    // ios::nocreate to control the use of PR_CREATE_FILE.

    if (flags == (ios_base::out)) {
        prflags = PR_WRONLY | PR_TRUNCATE;
    } else if (flags == (ios_base::out | ios_base::app)) {
        prflags = PR_RDWR | PR_APPEND;
    } else if (flags == (ios_base::out | ios_base::trunc)) {
        prflags = PR_WRONLY | PR_TRUNCATE;
    } else if (flags == (ios_base::in)) {
        prflags = PR_RDONLY;
    } else if (flags == (ios_base::in | ios_base::out)) {
        prflags = PR_RDWR;
    } else if (flags == (ios_base::in | ios_base::out | ios_base::trunc)) {
        prflags = PR_RDWR | PR_TRUNCATE;
    } else {
        return NULL;  // Unrecognized flag combination.
    }

    if ((_fd = PR_Open(name, prflags, mode)) == NULL) {
        return NULL;
    }

    _opened = true;

    if (ate &&
        seekoff(0, ios_base::end, flags) == pos_type(traits_type::eof())) {
        close();
        return NULL;
    }

    return this;
}


PRfilebuf *PRfilebuf::attach(PRFileDesc *fd)
{
    if (_fd != NULL) {
        return NULL;  // Error if already open.
    }

    _opened = false;
    _fd = fd;
    return this;
}


PRfilebuf *PRfilebuf::close()
{
    if (_fd == NULL) {
        return NULL;
    }

    int status = sync();

    if (PR_Close(_fd) == PR_FAILURE ||
        traits_type::eq_int_type(status, traits_type::eof())) {
        return NULL;
    }

    _fd = NULL;
    return this;
}


streambuf *PRfilebuf::setbuf(char_type *ptr, streamsize len)
{
    if (is_open() && _buf_end) {
        return NULL;
    }

    if (!ptr || len <= 0) {
        _unbuffered = true;
    } else {
        setb(ptr, ptr + len, false);
    }

    return this;
}


streambuf::pos_type PRfilebuf::seekoff(
    off_type offset, ios_base::seekdir dir, ios_base::openmode /*flags*/)
{
    if (PR_GetDescType(_fd) != PR_DESC_FILE) {
        return traits_type::eof();
    }

    PRSeekWhence whence;
    PRInt64 pos;

    switch (dir) {
        case ios_base::beg: whence = PR_SEEK_SET; break;
        case ios_base::cur: whence = PR_SEEK_CUR; break;
        case ios_base::end: whence = PR_SEEK_END; break;
        default:
            return traits_type::eof();  // This should never happen.
    }

    if (traits_type::eq_int_type(sync(), traits_type::eof())) {
        return traits_type::eof();
    }

    if ((pos = PR_Seek64(_fd, offset, whence)) == -1) {
        return traits_type::eof();
    }

    return pos;
}


int PRfilebuf::sync()
{
    if (_fd == NULL) {
        return traits_type::eof();
    }

    if (!_unbuffered) {
        // Sync write area.
        PRInt32 waiting;
        if ((waiting = pptr() - pbase()) != 0) {
            PRInt32 nout;
            if ((nout = PR_Write(_fd, pbase(), waiting)) != waiting) {
                if (nout > 0) {
                    // Should set _pptr -= nout.
                    pbump(-nout);
                    memmove(pbase(), pbase() + nout, waiting - nout);
                }
                return traits_type::eof();
            }
        }
        setp(NULL, NULL);  // Empty put area.

        if (PR_GetDescType(_fd) == PR_DESC_FILE) {
            // Sockets can't seek; don't need this.
            PROffset64 avail;
            if ((avail = in_avail()) > 0) {
                if (PR_Seek64(_fd, -avail, PR_SEEK_CUR) != -1) {
                    return traits_type::eof();
                }
            }
        }
        setg(NULL, NULL, NULL);  // Empty get area.
    }

    return 0;
}


streambuf::int_type PRfilebuf::underflow()
{
    PRInt32 count;
    char_type byte;

    if (gptr() != NULL && gptr() < egptr()) {
        return traits_type::to_int_type(*gptr());
    }

    // Make sure there is a reserve area.
    if (!_unbuffered && _buf_base == NULL && !allocate()) {
        return traits_type::eof();
    }

    // Sync before new buffer created below.
    if (traits_type::eq_int_type(sync(), traits_type::eof())) {
        return traits_type::eof();
    }

    if (_unbuffered) {
        if (PR_Read(_fd, &byte, 1) <= 0) {
            return traits_type::eof();
        }

        return traits_type::to_int_type(byte);
    }

    if ((count = PR_Read(_fd, _buf_base, _buf_end - _buf_base)) <= 0) {
        return traits_type::eof();  // Reached EOF.
    }

    setg(_buf_base, _buf_base, _buf_base + count);
    return traits_type::to_int_type(*gptr());
}


streambuf::int_type PRfilebuf::overflow(int_type c)
{
    // Make sure there is a reserve area.
    if (!_unbuffered && _buf_base == NULL && !allocate()) {
        return traits_type::eof();
    }

    // Sync before new buffer created below.
    if (traits_type::eq_int_type(sync(), traits_type::eof())) {
        return traits_type::eof();
    }

    if (!_unbuffered) {
        setp(_buf_base, _buf_end);
    }

    if (!traits_type::eq_int_type(c, traits_type::eof())) {
        // Extract the byte to be written.
        // (Required on big-endian architectures.)
        char_type byte = traits_type::to_char_type(c);
        if (!_unbuffered && pptr() < epptr()) {  // Guard against recursion.
            return sputc(byte);
        } else {
            if (PR_Write(_fd, &byte, 1) != 1) {
                return traits_type::eof();
            }
        }
    }

    return traits_type::not_eof(c);
}


bool PRfilebuf::allocate()
{
    char_type *buf = new(nothrow) char_type[BUFSIZ];
    if (buf == NULL) {
        return false;
    }

    setb(buf, buf + BUFSIZ, true);
    return true;
}


void PRfilebuf::setb(char_type *buf_base, char_type *buf_end, bool user_buf)
{
    if (_buf_base && !_user_buf) {
        delete[] _buf_base;
    }

    _buf_base = buf_base;
    _buf_end = buf_end;
    _user_buf = user_buf;
}


PRifstream::PRifstream():
    istream(NULL),
    _filebuf()
{
    init(&_filebuf);
}


PRifstream::PRifstream(PRFileDesc *fd):
    istream(NULL),
    _filebuf(fd)
{
    init(&_filebuf);
}


PRifstream::PRifstream(PRFileDesc *fd, char_type *ptr, streamsize len):
    istream(NULL),
    _filebuf(fd, ptr, len)
{
    init(&_filebuf);
}


PRifstream::PRifstream(const char *name, openmode flags, PRIntn mode):
    istream(NULL),
    _filebuf()
{
    init(&_filebuf);
    if (!_filebuf.open(name, flags | in, mode)) {
        setstate(failbit);
    }
}


PRifstream::~PRifstream() { }


void PRifstream::open(const char *name, openmode flags, PRIntn mode)
{
    if (is_open() || !_filebuf.open(name, flags | in, mode)) {
        setstate(failbit);
    }
}


void PRifstream::attach(PRFileDesc *fd)
{
    if (!_filebuf.attach(fd)) {
        setstate(failbit);
    }
}


void PRifstream::close()
{
    if (_filebuf.close() == NULL) {
        setstate(failbit);
    }
}


PRofstream::PRofstream():
    ostream(NULL),
    _filebuf()
{
    init(&_filebuf);
}


PRofstream::PRofstream(PRFileDesc *fd):
    ostream(NULL),
    _filebuf(fd)
{
    init(&_filebuf);
}


PRofstream::PRofstream(PRFileDesc *fd, char_type *ptr, streamsize len):
    ostream(NULL),
    _filebuf(fd, ptr, len)
{
    init(&_filebuf);
}


PRofstream::PRofstream(const char *name, openmode flags, PRIntn mode):
    ostream(NULL),
    _filebuf()
{
    init(&_filebuf);
    if (!_filebuf.open(name, flags | out, mode)) {
        setstate(failbit);
    }
}


PRofstream::~PRofstream() { }


void PRofstream::open(const char *name, openmode flags, PRIntn mode)
{
    if (is_open() || !_filebuf.open(name, flags | out, mode)) {
        setstate(failbit);
    }
}


void PRofstream::attach(PRFileDesc *fd)
{
    if (!_filebuf.attach(fd)) {
        setstate(failbit);
    }
}


void PRofstream::close()
{
    if (_filebuf.close() == NULL) {
        setstate(failbit);
    }
}


PRfstream::PRfstream():
    iostream(NULL),
    _filebuf()
{
    init(&_filebuf);
}


PRfstream::PRfstream(PRFileDesc *fd):
    iostream(NULL),
    _filebuf(fd)
{
    init(&_filebuf);
}


PRfstream::PRfstream(PRFileDesc *fd, char_type *ptr, streamsize len):
    iostream(NULL),
    _filebuf(fd, ptr, len)
{
    init(&_filebuf);
}


PRfstream::PRfstream(const char *name, openmode flags, PRIntn mode):
    iostream(NULL),
    _filebuf()
{
    init(&_filebuf);
    if (!_filebuf.open(name, flags | in | out, mode)) {
        setstate(failbit);
    }
}


PRfstream::~PRfstream() { }


void PRfstream::open(const char *name, openmode flags, PRIntn mode)
{
    if (is_open() || !_filebuf.open(name, flags | in | out, mode)) {
        setstate(failbit);
    }
}


void PRfstream::attach(PRFileDesc *fd)
{
    if (!_filebuf.attach(fd)) {
        setstate(failbit);
    }
}


void PRfstream::close()
{
    if (_filebuf.close() == NULL) {
        setstate(failbit);
    }
}

Messung V0.5
C=98 H=99 G=98

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.