1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// Mystream.cpp
// Implementation of ios interface classes for Myio
//
// Written by David L. Nugent
//
# include <iostream.h>
# include "Mystream.h"
# if defined(_MSC_VER)
# include <memory.h>
# else
# include <stdlib.h>
# endif
// Mystreambuf constructor
// This simply initialises the base class streambuf
// (it is initially empty with no buffer allocated)
// and register the Myio object
// Note: we _could_ set the stream unbuffered here,
// which is useful for stdio handles, so that the
// streambuf functions overflow() and underflow()
// get called on every character rather than when
// the streambuf buffer is full
Mystreambuf::Mystreambuf (Myio * mPtr)
: streambuf (), mptr(mPtr)
{
// unbuffered(1); // Uncomment to make unbuffered
}
// Mystreambuf()
// Called when streambuf owned buffer is full
// or when stream is flushed
// Our job here is to empty the streambuf
// write buffer and reset the 'put' pointers.
int
Mystreambuf::overflow (int c)
{
int written;
// Handle unbuffered stream
if (unbuffered()) // Handle the simple case first
{
if (c == EOF) // Special case, this only flushes
return 0;
char ch = char(c); // Write the byte directly
written = mptr->write (&ch, 1);
return (written) ? c : EOF;
}
// Handle buffered stream
if (!base()) // Need to allocate a buffer
allocate();
if (base()) // Test for memory allocation error
{
char * ep = base() + (blen() / 2);
if (!pbase()) // Set put pointers if not set up
setp (base(), ep);
int bytes = pptr() - pbase(); // Bytes to write
if (bytes)
{
written = mptr->write (pbase(), bytes);
if (!written)
return EOF;
bytes += written;
if (bytes) // Some is still waiting to be written
memcpy (base(), base() + written, bytes);
}
setp (base() + bytes, ep); // Reset 'put' pointers
return (c == EOF) ? 0 : sputc (c); // Put pending chr in buf
}
return EOF;
}
//
// underflow() indicates that the input queue
// is empty and needs more data
//
int
Mystreambuf::underflow (void)
{
int bytes;
// Handle an unbuffered stream
if (unbuffered())
{
bytes = mptr->read (&_back[1], 1);
if (!bytes)
{
setg (0, 0, 0);
return EOF;
}
setg (_back, _back + 1, _back + 2);
return (unsigned char)_back[1];
}
// Handle a buffered stream
if (!base()) // Need to allocate a buffer
allocate();
if (base())
{
char * gp = base() + blen() / 2;
if (gptr() >= egptr())
{ // Read into the buffer from stream
overflow (); // Flush output in case we need it
bytes = mptr->read (gp + 1, blen() / 2 - 1);
setg (gp, gp + 1, gp + bytes + 1);
}
if (gptr() < egptr()) // Get from buffer
return (unsigned char) *gptr();
}
return EOF;
}
//
// sync() needs to empty both put and get
// buffered. It will do this by calling
// overflow and simply resetting the get
// pointers to their default location.
//
int
Mystreambuf::sync (void)
{
if (!unbuffered())
{
overflow (); // Force output
char * gp = base();
setp (gp, gp + blen() / 2);
gp = base() + blen() / 2;
setg (0, 0, 0);
}
return 0;
}
|