1 /*
2    This file is part of libodbc++.
3 
4    Copyright (C) 1999-2000 Manush Dodunekov <manush@stendahls.net>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.  If not, write to
18    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.
20 */
21 
22 #ifndef __DATASTREAM_H
23 #define __DATASTREAM_H
24 
25 #include <odbc++/types.h>
26 
27 #if defined(ODBCXX_HAVE_ISO_CXXLIB)
28 # include <istream>
29 # include <streambuf>
30 #else
31 # include <iostream>
32 # include <streambuf.h>
33 #endif
34 
35 #include <cstdio> // for EOF
36 
37 #if defined(ODBCXX_QT)
38 # include <qiodevice.h>
39 #endif
40 
41 namespace odbc {
42 
43 #if !defined(ODBCXX_QT)
44 
45 
46    class DataStreamBuf : public ODBCXX_STREAMBUF {
47     friend class DataStreamBase;
48     friend class DataStream;
49   private:
50     ErrorHandler* errorHandler_;
51     SQLHSTMT hstmt_;
52     int column_;
53     int cType_;
54     DATASTATUS_TYPE& dataStatus_;
55     size_t bufferSize_;
56 
57     virtual int_type underflow();
58 
overflow(int)59     virtual int_type overflow(int) {
60       return EOF;
61     }
62 
sync()63     virtual int sync() {
64       //what can we do?
65       return 0;
66     }
67 
68     virtual
69 #if !defined(ODBCXX_HAVE_ISO_CXXLIB)
70     int
71 #else
72     std::streamsize
73 #endif
showmanyc()74     showmanyc() {
75       if(this->gptr() < this->egptr()) {
76 	return this->egptr() - this->gptr();
77       }
78       return 0;
79     }
80 
81     DataStreamBuf(ErrorHandler* eh, SQLHSTMT hstmt, int col, int cType,
82 		  DATASTATUS_TYPE& dataStatus);
83     virtual ~DataStreamBuf();
84   };
85 
86 #if !defined(ODBCXX_HAVE_ISO_CXXLIB)
87 
88   class DataStreamBase : public virtual ios {
89   private:
90     DataStreamBuf buf_;
91 
92   protected:
DataStreamBase(ErrorHandler * eh,SQLHSTMT hstmt,int column,int cType,DATASTATUS_TYPE & ds)93     DataStreamBase(ErrorHandler* eh, SQLHSTMT hstmt, int column,
94 		   int cType,DATASTATUS_TYPE& ds)
95       :buf_(eh,hstmt,column,cType,ds) {}
96 
~DataStreamBase()97     virtual ~DataStreamBase() {}
rdbuf()98     virtual DataStreamBuf* rdbuf() {
99       return &buf_;
100     }
101   };
102 
103   class DataStream : public DataStreamBase, public ODBCXX_STREAM
104 #else
105   class DataStream : public ODBCXX_STREAM
106 #endif
107   {
108     friend class ResultSet;
109     friend class PreparedStatement;
110     friend class Rowset;
111   private:
DataStream(ErrorHandler * eh,SQLHSTMT hstmt,int column,int cType,DATASTATUS_TYPE & ds)112     DataStream(ErrorHandler* eh, SQLHSTMT hstmt, int column, int cType,
113 	       DATASTATUS_TYPE& ds)
114       :
115 #if !defined(ODBCXX_HAVE_ISO_CXXLIB)
116       DataStreamBase(eh,hstmt,column,cType,ds),ODBCXX_STREAM(this->rdbuf())
117 #else
118 # if !defined(_MSC_VER)
119       ODBCXX_STREAM(ODBCXX_OPERATOR_NEW_DEBUG(__FILE__, __LINE__) odbc::DataStreamBuf(eh,hstmt,column,cType,ds))
120 # else
121       // Some bug in MSC makes it fail to realise that std::istream
122       // is inherited by this class
123       std::basic_istream<ODBCXX_CHAR_TYPE, std::char_traits<ODBCXX_CHAR_TYPE> >
124     (ODBCXX_OPERATOR_NEW_DEBUG(__FILE__, __LINE__) odbc::DataStreamBuf(eh,hstmt,column,cType,ds))
125 # endif // _MSC_VER
126 #endif
127     {
128 #ifndef THROWING_SHIT_IN_THE_CONSTRUCTOR_IS_A_BAD_IDEA_MAN
129   // fetch the first chunk of data - otherwise we don't know whether it's
130   // NULL or not
131 		odbc::DataStreamBuf* dsbuff = dynamic_cast<odbc::DataStreamBuf*>(rdbuf());
132 		if(dsbuff != NULL)
133 		{	dsbuff->underflow();}
134 #endif // THROWING_SHIT_IN_THE_CONSTRUCTOR_IS_A_BAD_IDEA_MAN
135 	  }
~DataStream()136     ~DataStream() {
137 #if defined(ODBCXX_HAVE_ISO_CXXLIB)
138       ODBCXX_OPERATOR_DELETE_DEBUG(__FILE__, __LINE__) this->rdbuf();
139 #endif
140     }
141   };
142 
143 #else // defined(ODBCXX_QT)
144 
145 
146   class DataStream : public QIODevice {
147   public:
148 
149 # if QT_VERSION >= 300
150     typedef QIODevice::Offset SizeType;
151     typedef Q_LONG BlockRetType;
152     typedef Q_ULONG BlockLenType;
153 # else
154     typedef uint SizeType;
155     typedef int BlockRetType;
156     typedef uint BlockLenType;
157 # endif
158 
159     DataStream(ErrorHandler* eh, SQLHSTMT hstmt, int column, int cType,
160 	       SQLINTEGER& ds);
161     virtual ~DataStream();
162 
163     virtual bool open(int) {
164       return false;
165     }
166 
167     virtual void close() {}
168     virtual void flush() {}
169 
170     virtual SizeType size() const {
171       return 0;
172     }
173 
174     virtual BlockRetType readBlock(char* data, BlockLenType len);
175 
176     // not writable
177     virtual BlockRetType writeBlock(const char* data, BlockLenType len) {
178       return -1;
179     }
180 
181     virtual int putch(int) {
182       return -1;
183     }
184 
185     virtual int ungetch(int) {
186       return -1;
187     }
188 
189     virtual int getch();
190 
191   private:
192     ErrorHandler* errorHandler_;
193     SQLHSTMT hstmt_;
194     int column_;
195     int cType_;
196     SQLINTEGER& dataStatus_;
197     size_t bufferStart_;
198     size_t bufferEnd_;
199     bool eof_;
200     size_t bufferSize_;
201     char* buffer_;
202 
203     void _readStep();
204   };
205 #endif
206 } // namespace odbc
207 
208 #endif //__DATASTREAM_H
209