1 /**************************************************************************/
2 /*                                                                        */
3 /*                                 OCaml                                  */
4 /*                                                                        */
5 /*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
6 /*                                                                        */
7 /*   Copyright 1996 Institut National de Recherche en Informatique et     */
8 /*     en Automatique.                                                    */
9 /*                                                                        */
10 /*   All rights reserved.  This file is distributed under the terms of    */
11 /*   the GNU Lesser General Public License version 2.1, with the          */
12 /*   special exception on linking described in the file LICENSE.          */
13 /*                                                                        */
14 /**************************************************************************/
15 
16 /* Buffered input/output */
17 
18 #ifndef CAML_IO_H
19 #define CAML_IO_H
20 
21 #ifdef CAML_INTERNALS
22 
23 #include "misc.h"
24 #include "mlvalues.h"
25 
26 #ifndef IO_BUFFER_SIZE
27 #define IO_BUFFER_SIZE 65536
28 #endif
29 
30 #if defined(_WIN32)
31 typedef __int64 file_offset;
32 #elif defined(HAS_OFF_T)
33 #include <sys/types.h>
34 typedef off_t file_offset;
35 #else
36 typedef long file_offset;
37 #endif
38 
39 struct channel {
40   int fd;                       /* Unix file descriptor */
41   file_offset offset;           /* Absolute position of fd in the file */
42   char * end;                   /* Physical end of the buffer */
43   char * curr;                  /* Current position in the buffer */
44   char * max;                   /* Logical end of the buffer (for input) */
45   void * mutex;                 /* Placeholder for mutex (for systhreads) */
46   struct channel * next, * prev;/* Double chaining of channels (flush_all) */
47   int revealed;                 /* For Cash only */
48   int old_revealed;             /* For Cash only */
49   int refcount;                 /* For flush_all and for Cash */
50   int flags;                    /* Bitfield */
51   char buff[IO_BUFFER_SIZE];    /* The buffer itself */
52   char * name;                  /* Optional name (to report fd leaks) */
53 };
54 
55 enum {
56   CHANNEL_FLAG_FROM_SOCKET = 1,  /* For Windows */
57 #if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
58   CHANNEL_FLAG_BLOCKING_WRITE = 2,
59 #endif
60 };
61 
62 /* For an output channel:
63      [offset] is the absolute position of the beginning of the buffer [buff].
64    For an input channel:
65      [offset] is the absolute position of the logical end of the buffer, [max].
66 */
67 
68 /* Functions and macros that can be called from C.  Take arguments of
69    type struct channel *.  No locking is performed. */
70 
71 #define caml_putch(channel, ch) do{                                       \
72   if ((channel)->curr >= (channel)->end) caml_flush_partial(channel);     \
73   *((channel)->curr)++ = (ch);                                            \
74 }while(0)
75 
76 #define caml_getch(channel)                                                 \
77   ((channel)->curr >= (channel)->max                                        \
78    ? caml_refill(channel)                                                   \
79    : (unsigned char) *((channel)->curr)++)
80 
81 CAMLextern struct channel * caml_open_descriptor_in (int);
82 CAMLextern struct channel * caml_open_descriptor_out (int);
83 CAMLextern void caml_close_channel (struct channel *);
84 CAMLextern int caml_channel_binary_mode (struct channel *);
85 CAMLextern value caml_alloc_channel(struct channel *chan);
86 
87 CAMLextern int caml_flush_partial (struct channel *);
88 CAMLextern void caml_flush (struct channel *);
89 CAMLextern void caml_putword (struct channel *, uint32_t);
90 CAMLextern int caml_putblock (struct channel *, char *, intnat);
91 CAMLextern void caml_really_putblock (struct channel *, char *, intnat);
92 
93 CAMLextern unsigned char caml_refill (struct channel *);
94 CAMLextern uint32_t caml_getword (struct channel *);
95 CAMLextern int caml_getblock (struct channel *, char *, intnat);
96 CAMLextern intnat caml_really_getblock (struct channel *, char *, intnat);
97 
98 /* Extract a struct channel * from the heap object representing it */
99 
100 #define Channel(v) (*((struct channel **) (Data_custom_val(v))))
101 
102 /* The locking machinery */
103 
104 CAMLextern void (*caml_channel_mutex_free) (struct channel *);
105 CAMLextern void (*caml_channel_mutex_lock) (struct channel *);
106 CAMLextern void (*caml_channel_mutex_unlock) (struct channel *);
107 CAMLextern void (*caml_channel_mutex_unlock_exn) (void);
108 
109 CAMLextern struct channel * caml_all_opened_channels;
110 
111 #define Lock(channel) \
112   if (caml_channel_mutex_lock != NULL) (*caml_channel_mutex_lock)(channel)
113 #define Unlock(channel) \
114   if (caml_channel_mutex_unlock != NULL) (*caml_channel_mutex_unlock)(channel)
115 #define Unlock_exn() \
116   if (caml_channel_mutex_unlock_exn != NULL) (*caml_channel_mutex_unlock_exn)()
117 
118 /* Conversion between file_offset and int64_t */
119 
120 #define Val_file_offset(fofs) caml_copy_int64(fofs)
121 #define File_offset_val(v) ((file_offset) Int64_val(v))
122 
123 #endif /* CAML_INTERNALS */
124 
125 #endif /* CAML_IO_H */
126