1/*
2    File:       CBufferSegment.c
3
4    Contains:   Implementation of the CBufferSegment class
5
6
7*/
8
9
10#include "CBufferSegment.h"
11#include "IrDALog.h"
12
13#if (hasTracing > 0 && hasCBufferSegTracing > 0)
14
15enum
16{
17    kLogNew = 1,
18    kLogNewWith,
19    kLogDelete,
20    kLogFree1,
21    kLogFree2,
22    kLogCBInit1,
23    kLogCBInit2,
24
25    kLogIOAllocBuf,
26    kLogIOAllocSize,
27    kLogIOFreeBuf,
28    kLogIOFreeSize
29};
30
31static
32EventTraceCauseDesc TraceEvents[] = {
33    {kLogNew,           "CBufferSegment:  New, obj="},
34    {kLogNewWith,       "CBufferSegment:  New hdr, obj=, buffer="},
35    {kLogDelete,        "CBufferSegment:  Delete"},
36    {kLogFree1,         "CBufferSegment:  Free, obj="},
37    {kLogFree2,         "CBufferSegment:  Free, buffer="},
38    {kLogCBInit1,       "CBufferSegment:  Init, length="},
39    {kLogCBInit2,       "CBufferSegment:  Init, buffer="},
40
41    {kLogIOAllocBuf,    "CBufferSegment: ioalloc, buffer="},
42    {kLogIOAllocSize,   "CBufferSegment: ioalloc, size="},
43    {kLogIOFreeBuf,     "CBufferSegment: iofree, buffer="},
44    {kLogIOFreeSize,    "CBufferSegment: iofree, size="}
45};
46#define XTRACE(x, y, z) IrDALogAdd( x, y, (uintptr_t)z & 0xffff, TraceEvents, true )
47#else
48#define XTRACE(x, y, z) ((void) 0)
49#endif
50
51#define super CBuffer
52    OSDefineMetaClassAndStructors(CBufferSegment, CBuffer);
53
54
55//--------------------------------------------------------------------------------
56//      CBufferSegment::New
57//          This is the preferred method (and easiest) of getting a statically
58//          allocated CbufferSegment and its associated buffer.  Initializes
59//          the object also.
60//
61//--------------------------------------------------------------------------------
62CBufferSegment * CBufferSegment::New(Size len)
63{
64#pragma unused(len)
65    //int Fix_Unused_Length;
66
67    CBufferSegment *obj = new CBufferSegment;
68
69    XTRACE(kLogNew, 0, obj);
70
71    if (obj && !obj->Init(nil, kDefaultCBufferSize)) {  // alloc a big buffer
72	obj->release();
73	obj = nil;
74    }
75
76    return obj;
77}
78
79CBufferSegment * CBufferSegment::New(UByte *buffer, Size len)
80{
81    CBufferSegment *obj = new CBufferSegment;
82
83    XTRACE(kLogNewWith, 0, obj);
84    XTRACE(kLogNewWith, 0, buffer);
85
86    if (obj && !obj->Init(buffer, len)) {
87	obj->release();
88	obj = nil;
89    }
90
91    return obj;
92}
93
94//--------------------------------------------------------------------------------
95//      CBufferSegment::Delete
96//          Old naming style, just calls release
97//--------------------------------------------------------------------------------
98/*void
99CBufferSegment::Delete()
100{
101    XTRACE( kLogDelete, (int)this >> 16, (int)this);
102
103    this->release();
104}*/
105
106//--------------------------------------------------------------------------------
107//      CBufferSegment::free
108//--------------------------------------------------------------------------------
109void
110CBufferSegment::free(void)
111{
112    XTRACE(kLogFree1, 0, this);
113    XTRACE(kLogFree2, (uintptr_t)fBufBase>>16, fBufBase);
114
115    if (fFreeMe && fBufBase) {
116	check(fSize);
117	XTRACE(kLogIOFreeBuf, 0, fBufBase);
118	XTRACE(kLogIOFreeSize, fSize >> 16, fSize);
119	IOFree(fBufBase, fSize);
120	fBufBase = nil;
121	fSize = 0;
122    }
123
124    super::free();
125}
126
127
128//--------------------------------------------------------------------------------
129//      CBufferSegment::init
130//--------------------------------------------------------------------------------
131Boolean CBufferSegment::Init(UByte *buffer, Size len)
132{
133    XTRACE(kLogCBInit1, 0, len);
134
135    fBufBase = nil;
136
137    if (!super::init()) return false;
138
139    if (buffer == nil) {            // callers wants us to alloc and free
140	fBufBase = (UByte*)IOMalloc(len);
141	XTRACE(kLogIOAllocBuf, 0, fBufBase);
142	XTRACE(kLogIOAllocSize, len >> 16, len);
143	require(fBufBase, Fail);
144	fFreeMe = true;
145    } else {
146	fBufBase = buffer;
147	fFreeMe = false;
148    }
149
150    XTRACE(kLogCBInit2, (uintptr_t)fBufBase>>16, fBufBase);
151
152    fSize = len;
153    fBufEnd = fBufBase + fSize;
154
155    // the whole buffer is available
156
157    fBase = fMark = fBufBase;
158    fEnd = fBufEnd;
159
160    return true;
161
162Fail:
163    return false;
164
165} // CBufferSegment::init
166
167
168//--------------------------------------------------------------------------------
169//      CBufferSegment::Peek
170//--------------------------------------------------------------------------------
171int CBufferSegment::Peek()
172{
173    return (fMark >= fEnd) ? EOF : *fMark;
174
175} // CBufferSegment::Peek
176
177
178//--------------------------------------------------------------------------------
179//      CBufferSegment::Next
180//--------------------------------------------------------------------------------
181int CBufferSegment::Next()
182{
183    return (fMark >= fEnd) ? EOF : *(++fMark);
184
185} // CBufferSegment::Next
186
187
188//--------------------------------------------------------------------------------
189//      CBufferSegment::Skip
190//--------------------------------------------------------------------------------
191uintptr_t CBufferSegment::Skip()
192{
193    return (fMark >= fEnd) ? EOF : (uintptr_t)fMark++;
194
195} // CBufferSegment::Skip
196
197
198//--------------------------------------------------------------------------------
199//      CBufferSegment::Get
200//--------------------------------------------------------------------------------
201int CBufferSegment::Get()
202{
203    return (fMark >= fEnd) ? EOF : *fMark++;
204
205} // CBufferSegment::Get
206
207
208//--------------------------------------------------------------------------------
209//      CBufferSegment::Getn
210//--------------------------------------------------------------------------------
211Size CBufferSegment::Getn(UByte* p, Size n)
212{
213    if (n > 0)
214	{
215	n = Min(n, fEnd - fMark);
216	if (n > 0)
217	    {
218	    BlockMove(fMark, p, n);
219	    fMark += n;
220	    }
221	}
222
223    return n;
224
225} // CBufferSegment::Getn
226
227
228//--------------------------------------------------------------------------------
229//      CBufferSegment::CopyOut
230//--------------------------------------------------------------------------------
231int CBufferSegment::CopyOut(UByte* p, Size& n)
232{
233    int result = 0;
234
235    if (n > 0)
236	{
237	n -= Getn(p, n);
238	if (fMark == fEnd)
239	    result = EOF;
240	}
241
242    return result;
243
244} // CBufferSegment::CopyOut
245
246
247//--------------------------------------------------------------------------------
248//      CBufferSegment::Put
249//--------------------------------------------------------------------------------
250int CBufferSegment::Put(int b)
251{
252    return (fMark >= fEnd) ? EOF : (*fMark++ = b);
253
254} // CBufferSegment::Put
255
256
257//--------------------------------------------------------------------------------
258//      CBufferSegment::Putn
259//--------------------------------------------------------------------------------
260Size CBufferSegment::Putn(const UByte* p, Size n)
261{
262    if (n > 0)
263	{
264	n = Min(n, fEnd - fMark);
265	if (n > 0)
266	    {
267	    BlockMove(p, fMark, n);
268	    fMark += n;
269	    }
270	}
271
272    return n;
273
274} // CBufferSegment::Putn
275
276
277//--------------------------------------------------------------------------------
278//      CBufferSegment::CopyIn
279//--------------------------------------------------------------------------------
280int CBufferSegment::CopyIn(const UByte* p, Size& n)
281{
282    int result = 0;
283
284    if (n > 0)
285	{
286	n -= Putn(p, n);
287	if (fMark == fEnd)
288	    return EOF;
289	}
290
291    return result;
292
293} // CBufferSegment::CopyIn
294
295
296//--------------------------------------------------------------------------------
297//      CBufferSegment::Reset
298//--------------------------------------------------------------------------------
299void CBufferSegment::Reset()
300{
301    fBase = fMark = fBufBase;
302    fEnd = fBufEnd;
303
304} // CBufferSegment::Reset
305
306
307//--------------------------------------------------------------------------------
308//      CBufferSegment::Hide
309//--------------------------------------------------------------------------------
310Size CBufferSegment::Hide(Long count, int dir)
311{
312    if (count == 0)
313	return 0;
314
315    switch (dir)
316	{
317	case kPosBeg:
318	    fBase += count;
319	    if (fBase < fBufBase)
320		{
321		count += (Long) (fBufBase - fBase);
322		fBase = fBufBase;
323		}
324	    else if (fBase > fBufEnd)
325		{
326		count -= (Long) (fBase - fBufEnd);
327		fBase = fBufEnd;
328		}
329	    fMark = fBase;
330	    break;
331
332	case kPosEnd:
333	    fEnd -= count;
334	    if (fEnd < fBufBase)
335		{
336		count -= (Long) (fBufBase - fEnd);
337		fEnd = fBufBase;
338		}
339	    else if (fEnd > fBufEnd)
340		{
341		count += (Long) (fEnd - fBufEnd);
342		fEnd = fBufEnd;
343		}
344	    fMark = fEnd;
345	    break;
346
347	default:
348	    count = 0;
349	    break;
350	}
351
352    return count;
353
354} // CBufferSegment::Hide
355
356
357//--------------------------------------------------------------------------------
358//      CBufferSegment::Seek
359//--------------------------------------------------------------------------------
360Size CBufferSegment::Seek(Long off, int dir)
361{
362    UByte* newPos;
363
364    // quick check for simple cases
365
366    if (off == 0)
367	{
368	if (dir == kPosBeg)
369	    fMark = fBase;
370
371	else if (dir == kPosEnd)
372	    fMark = fEnd;
373
374	else if (dir == kPosCur)
375	    /* no change */;
376	}
377
378    else
379	{
380	switch (dir)
381	    {
382	    case kPosBeg:
383		newPos = fBase + off;
384		break;
385
386	    case kPosCur:
387		newPos = fMark + off;
388		break;
389
390	    case kPosEnd:
391		newPos = fEnd - off;
392		break;
393
394	    default:
395		newPos = fMark;
396		break;
397	    }
398
399	fMark = (UByte*) UMinMax((uintptr_t) fBase, (uintptr_t) newPos, (uintptr_t) fEnd);
400	}
401
402    return (Size) (fMark - fBase);
403
404} // CBufferSegment::Seek
405
406
407//--------------------------------------------------------------------------------
408//      CBufferSegment::Position
409//--------------------------------------------------------------------------------
410Size CBufferSegment::Position() const
411{
412    return (Size) (fMark ? (fMark - fBase) : 0);
413
414} // CBufferSegment::Position
415
416
417//--------------------------------------------------------------------------------
418//      CBufferSegment::GetSize
419//--------------------------------------------------------------------------------
420Size CBufferSegment::GetSize() const
421{
422    return (Size) (fEnd - fBase);
423
424} // CBufferSegment::GetSize
425
426
427//--------------------------------------------------------------------------------
428//      CBufferSegment::AtEOF
429//--------------------------------------------------------------------------------
430Boolean CBufferSegment::AtEOF() const
431{
432    return (fMark == fEnd);
433
434} // CBufferSegment::AtEOF
435
436