|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // DBMS server stream buffer classes |
|
15 // |
|
16 // |
|
17 |
|
18 |
|
19 |
|
20 #include "SD_STD.H" |
|
21 |
|
22 HDbsBuf* HDbsBuf::NewLC(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs) |
|
23 { |
|
24 HDbsBuf* self=new(ELeave) HDbsBuf; |
|
25 self->PushL(); |
|
26 self->ConstructL(aObject,aFunction,aArgs); |
|
27 return self; |
|
28 } |
|
29 |
|
30 HDbsBuf* HDbsBuf::NewL(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs) |
|
31 { |
|
32 HDbsBuf* self=NewLC(aObject,aFunction,aArgs); |
|
33 CleanupStack::Pop(); |
|
34 return self; |
|
35 } |
|
36 |
|
37 void HDbsBuf::ConstructL(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs) |
|
38 { |
|
39 TPckg<TDbsStreamBuf> pckg(iBuf); |
|
40 aArgs.Set(3,&pckg); |
|
41 iIpc.OpenL(aObject,aFunction,aArgs); |
|
42 TUint8* base=iBuf.iData; |
|
43 // if reading we already have one buffer-full of data |
|
44 TInt avail=Max(0,Min(iBuf.iExt,KDbsStreamBufSize)); |
|
45 SetBuf(ERead,base,base+avail); |
|
46 SetPos(ERead,avail); |
|
47 SetBuf(EWrite,base,base); |
|
48 SetPos(EWrite,0); |
|
49 } |
|
50 |
|
51 TInt HDbsBuf::UnderflowL(TInt) |
|
52 // |
|
53 // Fill the buffer's read area. |
|
54 // |
|
55 { |
|
56 // when handle is null there is no data to read from server |
|
57 if(!iIpc.Handle()) |
|
58 return 0; |
|
59 |
|
60 __ASSERT(Avail(ERead)==0); |
|
61 TUint8* base=iBuf.iData; |
|
62 IpcWriteL(base,Lag(EWrite)); |
|
63 SetBuf(EWrite,base,base); |
|
64 // |
|
65 TInt len=IpcReadL(base,iBuf.ESize); |
|
66 SetBuf(ERead,base,base+len); |
|
67 return len; |
|
68 } |
|
69 |
|
70 void HDbsBuf::OverflowL() |
|
71 // |
|
72 // Set up the buffer's write area. |
|
73 // |
|
74 { |
|
75 __ASSERT(Avail(EWrite)==0); |
|
76 TUint8* base=iBuf.iData; |
|
77 MovePos(ERead,Lag(ERead)); |
|
78 SetBuf(ERead,base,base); |
|
79 // |
|
80 IpcWriteL(base,Lag(EWrite)); |
|
81 SetBuf(EWrite,base,base+iBuf.ESize); |
|
82 } |
|
83 |
|
84 void HDbsBuf::DoRelease() |
|
85 { |
|
86 delete this; |
|
87 } |
|
88 |
|
89 void HDbsBuf::DoSynchL() |
|
90 // |
|
91 // Synchronise this buffer with its file, giving up on outstanding writes in case of failure. |
|
92 // |
|
93 { |
|
94 TUint8* base=iBuf.iData; |
|
95 MovePos(ERead,Lag(ERead)); |
|
96 TInt lag=Lag(EWrite); |
|
97 SetBuf(ERead|EWrite,base,base); |
|
98 iBuf.iExt=-1; |
|
99 IpcWriteL(base,lag); |
|
100 iIpc.SendReceiveL(EDbsStreamSynch); |
|
101 } |
|
102 |
|
103 TInt HDbsBuf::DoReadL(TAny* aPtr,TInt aMaxLength) |
|
104 // |
|
105 // Read direct from ipc if asked to transfer more than a bufferful. |
|
106 // |
|
107 { |
|
108 __ASSERT(aMaxLength>=0); |
|
109 __ASSERT(aMaxLength>0); |
|
110 TInt avail=Avail(ERead); |
|
111 __ASSERT(avail>=0&&Avail(EWrite)>=0); |
|
112 if (avail>0) |
|
113 { |
|
114 TInt len=Min(aMaxLength,avail); |
|
115 TUint8* ptr=Ptr(ERead); |
|
116 aPtr=Mem::Copy(aPtr,ptr,len); |
|
117 SetPtr(ERead,ptr+len); |
|
118 aMaxLength-=len; |
|
119 if (aMaxLength==0) |
|
120 return len; // that's it |
|
121 } |
|
122 __ASSERT(Avail(ERead)==0); |
|
123 if (aMaxLength<iBuf.ESize) |
|
124 return avail+TStreamBuf::DoReadL(aPtr,aMaxLength); |
|
125 // |
|
126 // when handle is null there is no more data to read from server |
|
127 if(!iIpc.Handle()) |
|
128 return avail; |
|
129 |
|
130 TUint8* base=iBuf.iData; |
|
131 IpcWriteL(base,Lag(EWrite)); |
|
132 SetBuf(ERead|EWrite,base,base); |
|
133 return avail+IpcReadL(aPtr,aMaxLength); |
|
134 } |
|
135 |
|
136 void HDbsBuf::DoWriteL(const TAny* aPtr,TInt aLength) |
|
137 // |
|
138 // Write direct to ipc if asked to transfer more than a bufferful. |
|
139 // |
|
140 { |
|
141 __ASSERT(aLength>=0); |
|
142 __ASSERT(aLength>0); |
|
143 TInt avail=Avail(EWrite); |
|
144 __ASSERT(Avail(ERead)>=0&&avail>=0); |
|
145 if (avail>0) |
|
146 { |
|
147 TInt len=Min(aLength,avail); |
|
148 SetPtr(EWrite,Mem::Copy(Ptr(EWrite),aPtr,len)); |
|
149 aLength-=len; |
|
150 if (aLength==0) |
|
151 return; // done |
|
152 // |
|
153 aPtr=(TUint8*)aPtr+len; |
|
154 } |
|
155 __ASSERT(Avail(EWrite)==0); |
|
156 if (aLength<iBuf.ESize) |
|
157 TStreamBuf::DoWriteL(aPtr,aLength); |
|
158 else |
|
159 { |
|
160 TUint8* base=iBuf.iData; |
|
161 IpcWriteL(base,Lag(EWrite)); |
|
162 MovePos(ERead,Lag(ERead)); |
|
163 SetBuf(ERead|EWrite,base,base); |
|
164 IpcWriteL(aPtr,aLength); |
|
165 } |
|
166 } |
|
167 |
|
168 TStreamPos HDbsBuf::DoSeekL(TMark aMark,TStreamLocation aLocation,TInt anOffset) |
|
169 // |
|
170 // Position the mark(s) indicated by aMark at anOffset from aLocation. |
|
171 // |
|
172 { |
|
173 TUint8* base=iBuf.iData; |
|
174 TInt end=EndL(); |
|
175 // |
|
176 switch (aLocation) |
|
177 { |
|
178 case EStreamBeginning: |
|
179 break; |
|
180 case EStreamMark: |
|
181 switch (aMark) |
|
182 { |
|
183 case ERead: |
|
184 anOffset+=Mark(ERead); |
|
185 break; |
|
186 case EWrite: |
|
187 anOffset+=Mark(EWrite); |
|
188 break; |
|
189 default: |
|
190 Panic(EDbsStreamMarkInvalid); |
|
191 break; |
|
192 } |
|
193 break; |
|
194 case EStreamEnd: |
|
195 anOffset+=end; |
|
196 break; |
|
197 default: |
|
198 Panic(EDbsStreamLocationInvalid); |
|
199 break; |
|
200 } |
|
201 TInt r=KErrNone; |
|
202 if (anOffset<0) |
|
203 { |
|
204 anOffset=0; |
|
205 r=KErrEof; |
|
206 } |
|
207 else if (anOffset>end) |
|
208 { |
|
209 anOffset=end; |
|
210 r=KErrEof; |
|
211 } |
|
212 // |
|
213 __ASSERT_ALWAYS(!(aMark&~(ERead|EWrite)),Panic(EDbsStreamMarkInvalid)); |
|
214 if (aMark&ERead) |
|
215 { |
|
216 TInt lag=anOffset-Pos(ERead); |
|
217 if (lag>=base-End(ERead)&&lag<=0) |
|
218 SetPtr(ERead,End(ERead)+lag); |
|
219 else |
|
220 { |
|
221 SetPos(ERead,anOffset); |
|
222 SetBuf(ERead,base,base); |
|
223 } |
|
224 } |
|
225 if (aMark&EWrite&&anOffset!=Mark(EWrite)) |
|
226 { |
|
227 IpcWriteL(base,Lag(EWrite)); |
|
228 SetPos(EWrite,anOffset); |
|
229 SetBuf(EWrite,base,base); |
|
230 } |
|
231 __LEAVE_IF_ERROR(r); |
|
232 return TStreamPos(anOffset); |
|
233 } |
|
234 |
|
235 TInt HDbsBuf::IpcReadL(TAny* aPtr,TInt aMaxLength) |
|
236 // |
|
237 // Read from the server at the current read position. |
|
238 // |
|
239 { |
|
240 __ASSERT(aMaxLength>=0); |
|
241 if (aMaxLength==0) |
|
242 return 0; |
|
243 // |
|
244 TPtr8 des((TUint8*)aPtr,aMaxLength); |
|
245 TInt pos=Pos(ERead); |
|
246 |
|
247 TInt len=iIpc.SendReceiveL(EDbsStreamRead,TIpcArgs(pos,&des,aMaxLength)); |
|
248 pos+=len; |
|
249 if (len<aMaxLength) |
|
250 iBuf.iExt=pos; // end-of-file encountered |
|
251 SetPos(ERead,pos); |
|
252 return len; |
|
253 } |
|
254 |
|
255 void HDbsBuf::IpcWriteL(const TAny* aPtr,TInt aLength) |
|
256 // |
|
257 // Write to the server at the current write position. |
|
258 // |
|
259 { |
|
260 __ASSERT(aLength>=0); |
|
261 if (aLength==0) |
|
262 return; |
|
263 // |
|
264 TPtrC8 ptr((TUint8*)aPtr,aLength); |
|
265 TInt ext=iBuf.iExt; |
|
266 iBuf.iExt=-1; |
|
267 TInt pos=Pos(EWrite); |
|
268 iIpc.SendReceiveL(EDbsStreamWrite,TIpcArgs(pos,&ptr)); |
|
269 pos+=aLength; |
|
270 if (ext>=0&&pos>ext) |
|
271 iBuf.iExt=pos; |
|
272 SetPos(EWrite,pos); |
|
273 } |
|
274 |
|
275 TInt HDbsBuf::EndL() |
|
276 // |
|
277 // Determine the end of the stream |
|
278 // |
|
279 { |
|
280 TInt ext=iBuf.iExt; |
|
281 if (ext<0) |
|
282 iBuf.iExt=ext=iIpc.SendReceiveL(EDbsStreamSize); |
|
283 return Max(ext,Mark(EWrite)); |
|
284 } |
|
285 |
|
286 // Class HDbsReadBuf |
|
287 |
|
288 inline HDbsReadBuf::HDbsReadBuf(const TDesC8& aDes) |
|
289 { |
|
290 TUint8* ptr=CONST_CAST(TUint8*,aDes.Ptr()); |
|
291 Set(ptr,ptr+aDes.Length(),ERead); |
|
292 } |
|
293 |
|
294 HDbsReadBuf* HDbsReadBuf::NewL(const TDesC8& aDes) |
|
295 { |
|
296 return new(ELeave) HDbsReadBuf(aDes); |
|
297 } |
|
298 |
|
299 void HDbsReadBuf::DoRelease() |
|
300 { |
|
301 delete this; |
|
302 } |
|
303 |
|
304 // Class HDbsStream |
|
305 TInt HDbsStream::ReadL(const RMessage2& aMessage) |
|
306 { |
|
307 TInt pos=aMessage.Int0(); |
|
308 if (pos!=iRPos) |
|
309 iHost.SeekL(iHost.ERead,EStreamBeginning,pos); |
|
310 iRPos=-1; |
|
311 TInt len=aMessage.Int2(); |
|
312 pos+=len; |
|
313 TInt tfr=len; |
|
314 for (;;) |
|
315 { |
|
316 TUint8 buf[KDbsStreamIoSize]; |
|
317 TInt read=iHost.ReadL(buf,Min(tfr,KDbsStreamIoSize)); |
|
318 if (read==0) |
|
319 break; |
|
320 aMessage.WriteL(1,TPtrC8(buf,read),len-tfr); |
|
321 tfr-=read; |
|
322 if (tfr==0) |
|
323 break; |
|
324 if (read<KDbsStreamIoSize) |
|
325 break; |
|
326 } |
|
327 iRPos=pos-tfr; |
|
328 return len-tfr; |
|
329 } |
|
330 |
|
331 void HDbsStream::WriteL(const RMessage2& aMessage) |
|
332 { |
|
333 TInt pos=aMessage.Int0(); |
|
334 if (pos!=iWPos) |
|
335 iHost.SeekL(iHost.EWrite,EStreamBeginning,pos); |
|
336 iWPos=-1; |
|
337 TInt offset=0; |
|
338 TBuf8<KDbsStreamIoSize> buf; |
|
339 for (;;) |
|
340 { |
|
341 aMessage.ReadL(1,buf,offset); |
|
342 TInt len=buf.Length(); |
|
343 if (len==0) |
|
344 break; |
|
345 iHost.WriteL(buf.Ptr(),len); |
|
346 offset+=len; |
|
347 if (len<KDbsStreamIoSize) |
|
348 break; |
|
349 } |
|
350 iWPos=pos+offset; |
|
351 } |
|
352 |
|
353 // Class HBufBuf |
|
354 |
|
355 void HBufBuf::DoRelease() |
|
356 { |
|
357 delete this; |
|
358 } |
|
359 |
|
360 HBufBuf* HBufBuf::NewLC() |
|
361 { |
|
362 HBufBuf* self=new(ELeave) HBufBuf; |
|
363 self->PushL(); |
|
364 self->iBuf=CBufSeg::NewL(EGranularity); |
|
365 self->Set(*self->iBuf,0,ERead|EWrite); |
|
366 return self; |
|
367 } |
|
368 |