]> git.donarmstrong.com Git - lilypond.git/blob - guile18/test-suite/standalone/test-scm-c-read.c
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / test-suite / standalone / test-scm-c-read.c
1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17
18 /* Exercise `scm_c_read ()' and the port type API.  Verify assumptions that
19    can be made by port type implementations.  */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <libguile.h>
26 #include <assert.h>
27
28
29 \f
30 /* Size of our port's internal buffer.  */
31 #define PORT_BUFFER_SIZE 1024
32
33 /* Return a new port of type PORT_TYPE.  */
34 static inline SCM
35 make_port (scm_t_bits port_type)
36 {
37   SCM port;
38   char *c_buffer;
39   scm_t_port *c_port;
40
41   c_buffer = scm_gc_calloc (PORT_BUFFER_SIZE, "custom-port-buffer");
42
43   port = scm_new_port_table_entry (port_type);
44
45   /* Associate C_BUFFER with PORT, for test purposes.  */
46   SCM_SETSTREAM (port, (scm_t_bits) c_buffer);
47
48   /* Use C_BUFFER as PORT's internal buffer.  */
49   c_port = SCM_PTAB_ENTRY (port);
50   c_port->read_pos = c_port->read_buf = (unsigned char *) c_buffer;
51   c_port->read_end = (unsigned char *) c_buffer + PORT_BUFFER_SIZE;
52   c_port->read_buf_size = PORT_BUFFER_SIZE;
53
54   /* Mark PORT as open and readable.  */
55   SCM_SET_CELL_TYPE (port, port_type | SCM_OPN | SCM_RDNG);
56
57   return port;
58 }
59
60 /* Read one byte from PORT.  */
61 static int
62 fill_input (SCM port)
63 {
64   int result;
65   scm_t_port *c_port = SCM_PTAB_ENTRY (port);
66
67   /* Make sure that C_PORT's internal buffer wasn't changed behind our back.
68      See http://lists.gnu.org/archive/html/guile-devel/2008-11/msg00042.html
69      for an example where this assumption matters.  */
70   assert (c_port->read_buf == (unsigned char *) SCM_STREAM (port));
71   assert (c_port->read_buf_size == PORT_BUFFER_SIZE);
72
73   if (c_port->read_pos >= c_port->read_end)
74     result = EOF;
75   else
76     result = (int) *c_port->read_pos++;
77
78   return result;
79 }
80
81 /* Return true (non-zero) if BUF contains only zeros.  */
82 static inline int
83 zeroed_buffer_p (const char *buf, size_t len)
84 {
85   size_t i;
86
87   for (i = 0; i < len; i++)
88     if (buf[i] != 0)
89       return 0;
90
91   return 1;
92 }
93
94 /* Run the test.  */
95 static void *
96 do_start (void *arg)
97 {
98   SCM port;
99   scm_t_bits port_type;
100   char buffer[PORT_BUFFER_SIZE + (PORT_BUFFER_SIZE / 2)];
101   size_t read, last_read;
102
103   port_type = scm_make_port_type ("custom-input-port", fill_input, NULL);
104   port = make_port (port_type);
105
106   read = 0;
107   do
108     {
109       last_read = scm_c_read (port, &buffer[read], 123);
110       assert (last_read <= 123);
111       assert (zeroed_buffer_p (&buffer[read], last_read));
112
113       read += last_read;
114     }
115   while (last_read > 0 && read < sizeof (buffer));
116
117   /* We shouldn't be able to read more than what's in PORT's buffer.  */
118   assert (read == PORT_BUFFER_SIZE);
119
120   return NULL;
121 }
122
123 \f
124 int
125 main (int argc, char *argv[])
126 {
127   scm_with_guile (do_start, NULL);
128
129   return 0;
130 }