1//----------------------------------------------------------------------
2//  This software is part of the Haiku distribution and is covered
3//  by the MIT License.
4//---------------------------------------------------------------------
5/*!
6	\file OffsetFile.cpp
7	OffsetFile implementation.
8*/
9
10#include <stdio.h>
11
12#include "OffsetFile.h"
13
14namespace BPrivate {
15namespace Storage {
16
17// constructor
18OffsetFile::OffsetFile()
19	: fFile(NULL),
20	  fOffset(0),
21	  fCurrentPosition(0)
22{
23}
24
25// constructor
26OffsetFile::OffsetFile(BFile *file, off_t offset)
27	: fFile(NULL),
28	  fOffset(0),
29	  fCurrentPosition(0)
30{
31	SetTo(file, offset);
32}
33
34// destructor
35OffsetFile::~OffsetFile()
36{
37}
38
39// SetTo
40status_t
41OffsetFile::SetTo(BFile *file, off_t offset)
42{
43	Unset();
44	fFile = file;
45	fOffset = offset;
46	return fFile->InitCheck();
47}
48
49// Unset
50void
51OffsetFile::Unset()
52{
53	fFile = NULL;
54	fOffset = 0;
55	fCurrentPosition = 0;
56}
57
58// InitCheck
59status_t
60OffsetFile::InitCheck() const
61{
62	return (fFile ? fFile->InitCheck() : B_NO_INIT);
63}
64
65// File
66BFile *
67OffsetFile::File() const
68{
69	return fFile;
70}
71
72// ReadAt
73ssize_t
74OffsetFile::ReadAt(off_t pos, void *buffer, size_t size)
75{
76	status_t error = InitCheck();
77	ssize_t result = 0;
78	if (error == B_OK)
79		result = fFile->ReadAt(pos + fOffset, buffer, size);
80	return (error == B_OK ? result : error);
81}
82
83// WriteAt
84ssize_t
85OffsetFile::WriteAt(off_t pos, const void *buffer, size_t size)
86{
87	status_t error = InitCheck();
88	ssize_t result = 0;
89	if (error == B_OK)
90		result = fFile->WriteAt(pos + fOffset, buffer, size);
91	return (error == B_OK ? result : error);
92}
93
94// Seek
95off_t
96OffsetFile::Seek(off_t position, uint32 seekMode)
97{
98	off_t result = B_BAD_VALUE;
99	status_t error = InitCheck();
100	if (error == B_OK) {
101		switch (seekMode) {
102			case SEEK_SET:
103				if (position >= 0)
104					result = fCurrentPosition = position;
105				break;
106			case SEEK_END:
107			{
108				off_t size;
109				error = GetSize(&size);
110				if (error == B_OK) {
111					if (size + position >= 0)
112						result = fCurrentPosition = size + position;
113				}
114				break;
115			}
116			case SEEK_CUR:
117				if (fCurrentPosition + position >= 0)
118					result = fCurrentPosition += position;
119				break;
120			default:
121				break;
122		}
123	}
124	return (error == B_OK ? result : error);
125}
126
127// Position
128off_t
129OffsetFile::Position() const
130{
131	return fCurrentPosition;
132}
133
134// SetSize
135status_t
136OffsetFile::SetSize(off_t size)
137{
138	status_t error = (size >= 0 ? B_OK : B_BAD_VALUE );
139	if (error == B_OK)
140		error = InitCheck();
141	if (error == B_OK)
142		error = fFile->SetSize(size + fOffset);
143	return error;
144}
145
146// GetSize
147status_t
148OffsetFile::GetSize(off_t *size) const
149{
150	status_t error = (size ? B_OK : B_BAD_VALUE );
151	if (error == B_OK)
152		error = InitCheck();
153	if (error == B_OK)
154		error = fFile->GetSize(size);
155	if (error == B_OK) {
156		*size -= fOffset;
157		if (*size < 0)
158			*size = 0;
159	}
160	return error;
161}
162
163// Offset
164off_t
165OffsetFile::Offset() const
166{
167	return fOffset;
168}
169
170};	// namespace Storage
171};	// namespace BPrivate
172