Skip to content

Instantly share code, notes, and snippets.

@Alexis-D
Created July 28, 2011 13:35
Show Gist options
  • Save Alexis-D/1111559 to your computer and use it in GitHub Desktop.
Save Alexis-D/1111559 to your computer and use it in GitHub Desktop.
stdio
/*
* Alexis Daboville - 2011
*/
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "stdio.h"
#define MAX_FILE 1024
/*
* Pas de gestion des erreurs
* Alloué un buffer en écriture dans _flsbuf si nécessaire.
*/
struct _iobuf _IOB[MAX_FILE] = {
{ 0, NULL, NULL, 0, _IOREAD, 0 },
{ 0, NULL, NULL, 0, _IOWRT | _IOLBF, 1 },
{ 0, NULL, NULL, 0, _IOWRT | _IONBF, 2 }
};
/*
* Remplit le buffer de p, et alloue le buffer si ça n'a pas été fait.
*/
int _filbuf(FILE *p) {
//si on a pas de buffer, on en alloue un
if(!p->_base) {
if(!p->_bufsiz) {
p->_bufsiz = BUFSIZ;
}
p->_base = malloc(p->_bufsiz);
}
//on lit les carctères, et on place _ptr au début du buffer
p->_cnt = read(p->_file, p->_base, p->_bufsiz);
p->_ptr = p->_base;
if(p->_cnt) {
--p->_cnt;
return *p->_ptr++;
}
return EOF;
}
/*
* Flush le buffer de p, et affiche c.
*/
int _flsbuf(int c, FILE *p) {
//si on est pas bufferisé, on écrit le carctère (e.g. stderr)
if(p->_flag & _IONBF) {
write(p->_file, &c, 1);
return c;
}
//si on a pas de buffer, on en alloue un
if(!p->_base) {
if(!p->_bufsiz) {
p->_bufsiz = BUFSIZ;
}
p->_ptr = p->_base = malloc(p->_bufsiz);
p->_cnt = 0;
//on ajoute le caractère au buffer
return putc(c, p);
}
//si on est line buffered et que le buffer n'est pas plein
//on le vide
if(p->_flag & _IOLBF && -p->_cnt < p->_bufsiz) {
write(p->_file, p->_base, -p->_cnt);
p->_ptr = p->_base;
p->_cnt = 0;
}
else {
//s'il reste de la place dans le buffer on le vide (+1 pour le denier char)
if(p->_cnt >= 0) {
write(p->_file, p->_base, p->_ptr - p->_base + 1);
p->_ptr = p->_base;
p->_cnt = p->_bufsiz;
}
//le buffer est plein : on le vide, et on mets c dedans
else {
write(p->_file, p->_base, p->_ptr - p->_base);
p->_ptr = p->_base;
p->_cnt = p->_flag & _IOLBF ? 0 : p->_bufsiz;
putc(c, p);
}
}
return c;
}
/*
* Force le flush du buffer de stream.
*/
int fflush(FILE *stream) {
return stream->_cnt == 0 ? 0 :_flsbuf((int) *--stream->_ptr, stream);
}
/*
* Ouvre le fichier à l'adresse path selon le mode mode, man 3 fopen
* pour voir les modes disponibles.
*/
/*
* Comment gérer r+, w+, a. avec un seul buffer ?
*/
FILE *fopen(const char *path, const char *mode) {
int fd;
if(strcmp(mode, "r") == 0) {
fd = open(path, O_RDONLY);
_IOB[fd]._flag = _IOREAD;
_IOB[fd]._cnt = 0;
}
else if(strcmp(mode, "w") == 0) {
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
_IOB[fd]._flag = _IOWRT | _IOFBF;
}
else if(strcmp(mode, "a") == 0) {
fd = open(path, O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
_IOB[fd]._flag = _IOWRT | _IOFBF;
}
_IOB[fd]._bufsiz = 0;
_IOB[fd]._ptr = _IOB[fd]._base = NULL;
_IOB[fd]._file = fd;
return &_IOB[fd];
}
/*
* Ferme le fichier stream, et désalloue le buffer s'il
* y en a un.
*/
int fclose(FILE *stream) {
fflush(stream);
if(stream->_base) {
free(stream->_base);
}
return close(stream->_file);
}
/*
* man 3 setbuf
*/
void setbuf(FILE *stream, char *buf) {
setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
}
/*
* man 3 setvbuf
*/
int setvbuf(FILE *stream, char *buf, int mode, int size) {
stream->_ptr = stream->_base = buf;
stream->_bufsiz = size;
stream->_flag &= (~_IOLBF | ~_IOFBF | ~_IONBF);
stream->_flag |= mode;
if(~stream->_flag & _IOLBF && stream->_flag & _IOWRT) {
stream->_cnt = size;
}
else {
stream->_cnt = 0;
}
return 0;
}
int _fprintf(FILE *stream, const char *format, va_list ap) {
int a, i = 0, c, count = 0, base, j, mod;
bool modifier = false, hexa = false;
char *b, buff[8 * sizeof (int)];
while(c = (int) format[i]) {
if(modifier) {
++count;
modifier = false;
switch(c) {
case '%':
putc(c, stream);
break;
case 'c':
a = va_arg(ap, int);
putc(a, stream);
break;
case 's':
b = va_arg(ap, char*);
--count;
while(*b) {
putc(*b, stream);
++b;
++count;
}
break;
case 'x':
hexa = true;
case 'd':
a = va_arg(ap, int);
base = hexa ? 16 : 10;
j = sizeof(buff);
b = buff;
b[--j] = 0;
if(a < 0) {
putc('-', stream);
}
do {
--j;
mod = a % base;
a /= base;
b[j] = mod + (mod < 10 ? '0' : 'a' - 10);
} while(a != 0);
b = buff + j;
while(*b) {
putc(*b, stream);
++b;
}
hexa = false;
break;
default:
return -1;
}
}
else if(format[i] == '%') {
modifier = true;
}
else {
++count;
putc(c, stream);
}
++i;
}
return count;
}
int fprintf(FILE *stream, const char *format, ...) {
va_list ap;
int c;
va_start(ap, format);
c = _fprintf(stream, format, ap);
va_end(ap);
return c;
}
int printf(const char *format, ...) {
va_list ap;
int c;
va_start(ap, format);
c = _fprintf(stdout, format, ap);
va_end(ap);
return c;
}
/***
*
* Re-ecriture des fonctions de base de stdio
*
* Author: Erick Gallesio [[email protected]]
* Creation date: 27-Oct-1992 09:28
* Last file update: 6-Mar-2011 22:21 (eg)
*
*/
/**** Ce qui suit est le fichier standard stdio.h de Sun OS 4.x
(legerement modifie) ****/
# ifndef FILE
#define BUFSIZ 1024
#define _SBFSIZ 8
extern struct _iobuf {
int _cnt;
unsigned char* _ptr;
unsigned char* _base;
int _bufsiz;
short _flag;
char _file;
} _IOB[];
#define _IOFBF 0
#define _IOREAD 01
#define _IOWRT 02
#define _IONBF 04
#define _IOMYBUF 010
#define _IOEOF 020
#define _IOERR 040
#define _IOSTRG 0100
#define _IOLBF 0200
#define _IORW 0400
#define NULL ((void*) 0)
#define FILE struct _iobuf
#define EOF (-1)
#define stdin (&_IOB[0])
#define stdout (&_IOB[1])
#define stderr (&_IOB[2])
#ifdef lint /* so that lint likes (void)putc(a,b) */
extern int putc();
extern int getc();
#else
#define getc(p) (--(p)->_cnt>=0? ((int)*(p)->_ptr++):_filbuf(p))
#define putc(x, p) (--(p)->_cnt >= 0 ?\
(int)(*(p)->_ptr++ = (unsigned char)(x)) :\
(((p)->_flag & _IOLBF) && -(p)->_cnt < (p)->_bufsiz ?\
((*(p)->_ptr = (unsigned char)(x)) != '\n' ?\
(int)(*(p)->_ptr++) :\
_flsbuf(*(unsigned char *)(p)->_ptr, p)) :\
_flsbuf((unsigned char)(x), p)))
#endif
#define getchar() getc(stdin)
#define putchar(x) putc((x),stdout)
#define feof(p) (((p)->_flag&_IOEOF)!=0)
#define ferror(p) (((p)->_flag&_IOERR)!=0)
#define fileno(p) ((p)->_file)
#define clearerr(p) (void) ((p)->_flag &= ~(_IOERR|_IOEOF))
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
int fclose(FILE *fp);
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
FILE *tmpfile(void);
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
char *gets(char *s);
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode, int size);
# endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment