blob: 0c91f8c8b0b408deeb7e9952864eb8fd7eb87aea [file] [log] [blame]
/*
* Copyright (c) 2012 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* NaCl Generic I/O interface.
*/
#ifndef NATIVE_CLIENT_SRC_SHARED_GIO_GIO_H_
#define NATIVE_CLIENT_SRC_SHARED_GIO_GIO_H_
/* is this needed? - maybe for size_t */
#include "native_client/src/include/portability.h"
#include <stdarg.h>
#include <stdio.h>
EXTERN_C_BEGIN
struct Gio; /* fwd */
/*
* In the generic I/O package, -1 is used consistently to indicate
* error. Check the return value for equality to -1 and do not check
* that it's negative.
*
* Here's the rationale. Note that the Read and Write virtual
* functions, like the read/write system calls, return ssize_t but
* takes a count argument that's of type size_t. Since
* sizeof(ssize_t) == sizeof(size_t), this means that we either never
* perform the full operation if the count argument would be negative
* if viewed as an ssize_t, or we just do it and expect the caller to
* do the right thing. The only negative value that we reserve as an
* error indication is -1, and this is also an unreasonable input
* value on any sane, von-Neumann machine: there must be at least one
* byte of code in the address space, and at least for Read, is
* read-only text, and for Write it is extremely unlikely that any
* application will want to write out (almost) the entire address
* space.
*
* When -1 is used to indicate an error, errno is set to indicate the
* error.
*/
struct GioVtbl {
/*
* Will implicitly close if not already closed, but no error
* reporting, other than possibly logging.
*/
void (*Dtor)(struct Gio *vself);
/*
* Read virtual fn. Like read syscall: returns number of bytes
* actually read, -1 on error, so 0 indcates EOF. Depending on
* subclass, there may be short reads even before EOF, but all short
* reads must return at least one byte, so that this is
* distinguishable from EOF.
*/
ssize_t (*Read)(struct Gio *vself,
void *buf,
size_t count);
/*
* Write virtual fn. Like write syscall: returns number of bytes
* actually written, -1 on error. Depending on subclass, there may
* be short writes.
*/
ssize_t (*Write)(struct Gio *vself,
const void *buf,
size_t count);
/*
* Seek virtual function. Like the lseek syscall. whence is one of
* SEEK_SET, SEEK_CUR, SEEK_END. There is no ftell -- use
* Seek(self, 0, SEEK_CUR) to obtain the current position. Whether
* seeking beyond the end of an Gio object and writing results in
* defined behavior depends on the subclass involved, i.e., some
* subclasses may grow/extend the object (e.g., file, shared
* memory), and others may not (e.g., in-memory snapshot).
*/
off_t (*Seek)(struct Gio *vself,
off_t offset,
int whence);
/* Only used for write, 0 on success, -1 on error */
int (*Flush)(struct Gio *vself);
/*
* Returns 0 on success, -1 on error. Implicitly Flush. If Flush
* succeeds, deallocate system-level resources. After Close, no
* other operations should be performed other than Dtor. Close
* might be merged with the Dtor, except that the Dtor cannot report
* errors.
*/
int (*Close)(struct Gio *vself);
};
struct Gio {
struct GioVtbl const *vtbl;
};
struct GioFile {
struct Gio base;
FILE *iop;
};
int GioFileCtor(struct GioFile *self,
char const *fname,
char const *mode);
ssize_t GioFileRead(struct Gio *vself,
void *buf,
size_t count);
ssize_t GioFileWrite(struct Gio *vself,
const void *buf,
size_t count);
off_t GioFileSeek(struct Gio *vself,
off_t offset,
int whence);
int GioFileFlush(struct Gio *vself);
int GioFileClose(struct Gio *vself);
void GioFileDtor(struct Gio *vself);
int GioFileRefCtor(struct GioFile *self,
FILE *iop);
size_t gprintf(struct Gio *gp,
char const *fmt,
...);
size_t gvprintf(struct Gio *gp,
char const *fmt,
va_list ap);
EXTERN_C_END
#endif /* NATIVE_CLIENT_SRC_SHARED_GIO_GIO_H_ */