2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / FirebirdSql.Data.Firebird / FirebirdSql.Data.Common / BlobBase.cs
1 /*
2  *  Firebird ADO.NET Data provider for .NET and Mono 
3  * 
4  *     The contents of this file are subject to the Initial 
5  *     Developer's Public License Version 1.0 (the "License"); 
6  *     you may not use this file except in compliance with the 
7  *     License. You may obtain a copy of the License at 
8  *     http://www.firebirdsql.org/index.php?op=doc&id=idpl
9  *
10  *     Software distributed under the License is distributed on 
11  *     an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either 
12  *     express or implied.  See the License for the specific 
13  *     language governing rights and limitations under the License.
14  * 
15  *  Copyright (c) 2002, 2004 Carlos Guzman Alvarez
16  *  All Rights Reserved.
17  */
18
19 using System;
20 using System.Data;
21 using System.Text;
22 using System.IO;
23 using System.Collections;
24
25 namespace FirebirdSql.Data.Common
26 {
27         internal abstract class BlobBase
28         {
29                 #region Fields
30
31                 private int             rblFlags;
32                 private Charset charset;
33                 private int             segmentSize;
34
35                 #endregion
36
37                 #region Protected Fields
38
39                 protected long                  blobId;
40                 protected int                   blobHandle;
41                 protected int                   position;
42                 protected ITransaction  transaction;
43
44                 #endregion
45
46                 #region Properties
47
48                 public int Handle
49                 {
50                         get { return this.blobHandle; }
51                 }
52
53                 public long Id
54                 {
55                         get { return this.blobId; }
56                 }
57
58                 public bool EOF
59                 {
60                         get { return (this.rblFlags & IscCodes.RBL_eof_pending) != 0; }
61                 }
62
63                 #endregion
64
65                 #region Protected Properties
66
67                 protected int SegmentSize
68                 {
69                         get { return this.segmentSize; }
70                 }
71
72                 #endregion
73
74                 #region Abstract Properties
75
76                 public abstract IDatabase DB
77                 {
78                         get;
79                 }
80
81                 #endregion
82
83                 #region Constructors
84
85                 protected BlobBase(IDatabase db)
86                 {
87                         this.segmentSize        = db.PacketSize;
88                         this.charset            = db.Charset;
89                 }
90
91                 #endregion
92
93                 #region Protected Abstract Methods
94
95                 protected abstract void Create();
96                 protected abstract void Open();
97                 protected abstract byte[] GetSegment();
98                 protected abstract void PutSegment(byte[] buffer);
99                 protected abstract void Seek(int position);
100                 protected abstract void GetBlobInfo();
101                 protected abstract void Close();
102                 protected abstract void Cancel();
103
104                 #endregion
105
106                 #region Methods
107
108                 public string ReadString()
109                 {
110                         byte[] buffer = this.Read();
111                         return this.charset.GetString(buffer, 0, buffer.Length);
112                 }
113
114                 public byte[] Read()
115                 {
116                         MemoryStream ms = new MemoryStream();
117
118                         try
119                         {
120                                 this.Open();
121
122                                 while (!EOF)
123                                 {
124                                         byte[] segment = this.GetSegment();
125                                         ms.Write(segment, 0, segment.Length);
126                                 }
127
128                                 this.Close();
129                         }
130                         catch (Exception)
131                         {
132                                 // Cancel the blob and rethrow the exception
133                                 this.Cancel();
134
135                                 throw;
136                         }
137
138                         return ms.ToArray();
139                 }
140
141                 public void Write(string data)
142                 {
143                         this.Write(this.charset.GetBytes(data));
144                 }
145
146                 public void Write(byte[] buffer)
147                 {
148                         this.Write(buffer, 0, buffer.Length);
149                 }
150
151                 public void Write(byte[] buffer, int index, int count)
152                 {
153                         try
154                         {
155                                 this.Create();
156
157                                 byte[] tmpBuffer = null;
158
159                                 int length = count;
160                                 int offset = index;
161                                 int chunk = length >= this.segmentSize ? this.segmentSize : length;
162
163                                 tmpBuffer = new byte[chunk];
164
165                                 while (length > 0)
166                                 {
167                                         if (chunk > length)
168                                         {
169                                                 chunk = (int)length;
170                                                 tmpBuffer = new byte[chunk];
171                                         }
172                                         System.Array.Copy(buffer, offset, tmpBuffer, 0, chunk);
173                                         this.PutSegment(tmpBuffer);
174
175                                         offset += chunk;
176                                         length -= chunk;
177                                 }
178
179                                 this.Close();
180                         }
181                         catch (Exception)
182                         {
183                                 // Cancel the blob and rethrow the exception
184                                 this.Cancel();
185
186                                 throw;
187                         }
188                 }
189
190                 #endregion
191
192                 #region Protected Methods
193
194                 protected void RblAddValue(int rblValue)
195                 {
196                         this.rblFlags |= rblValue;
197                 }
198
199                 protected void RblRemoveValue(int rblValue)
200                 {
201                         this.rblFlags &= ~rblValue;
202                 }
203
204                 #endregion
205         }
206 }