Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PCIDSK Database File
4 : * Purpose: PCIDSK SDK compatible IO interface built on VSI.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2010, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_multiproc.h"
16 : #include "pcidsk.h"
17 :
18 : using PCIDSK::IOInterfaces;
19 : using PCIDSK::PCIDSKInterfaces;
20 : using PCIDSK::ThrowPCIDSKException;
21 : using PCIDSK::uint64;
22 :
23 : PCIDSK::EDBFile *GDAL_EDBOpen(const std::string &osFilename,
24 : const std::string &osAccess);
25 : const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces();
26 :
27 : class VSI_IOInterface final : public IOInterfaces
28 : {
29 : void *Open(const std::string &filename,
30 : const std::string &access) const override;
31 : uint64 Seek(void *io_handle, uint64 offset, int whence) const override;
32 : uint64 Tell(void *io_handle) const override;
33 : uint64 Read(void *buffer, uint64 size, uint64 nmemb,
34 : void *io_hanle) const override;
35 : uint64 Write(const void *buffer, uint64 size, uint64 nmemb,
36 : void *io_handle) const override;
37 : int Eof(void *io_handle) const override;
38 : int Flush(void *io_handle) const override;
39 : int Close(void *io_handle) const override;
40 :
41 : const char *LastError() const;
42 : };
43 :
44 : /************************************************************************/
45 : /* PCIDSK2GetIOInterfaces() */
46 : /************************************************************************/
47 :
48 260 : const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces()
49 : {
50 260 : static VSI_IOInterface singleton_vsi_interface;
51 260 : static PCIDSKInterfaces singleton_pcidsk2_interfaces;
52 :
53 260 : singleton_pcidsk2_interfaces.io = &singleton_vsi_interface;
54 260 : singleton_pcidsk2_interfaces.OpenEDB = GDAL_EDBOpen;
55 :
56 260 : return &singleton_pcidsk2_interfaces;
57 : }
58 :
59 : /************************************************************************/
60 : /* Open() */
61 : /************************************************************************/
62 :
63 389 : void *VSI_IOInterface::Open(const std::string &filename,
64 : const std::string &access) const
65 :
66 : {
67 389 : VSILFILE *fp = VSIFOpenL(filename.c_str(), access.c_str());
68 :
69 389 : if (fp == nullptr)
70 5 : ThrowPCIDSKException("Failed to open %s: %s", filename.c_str(),
71 : LastError());
72 :
73 384 : return fp;
74 : }
75 :
76 : /************************************************************************/
77 : /* Seek() */
78 : /************************************************************************/
79 :
80 17444 : uint64 VSI_IOInterface::Seek(void *io_handle, uint64 offset, int whence) const
81 :
82 : {
83 17444 : VSILFILE *fp = reinterpret_cast<VSILFILE *>(io_handle);
84 :
85 17444 : uint64 result = VSIFSeekL(fp, offset, whence);
86 :
87 17444 : if (result == static_cast<uint64>(-1))
88 0 : ThrowPCIDSKException("Seek(%d,%d): %s", static_cast<int>(offset),
89 : whence, LastError());
90 :
91 17444 : return result;
92 : }
93 :
94 : /************************************************************************/
95 : /* Tell() */
96 : /************************************************************************/
97 :
98 1 : uint64 VSI_IOInterface::Tell(void *io_handle) const
99 :
100 : {
101 1 : VSILFILE *fp = reinterpret_cast<VSILFILE *>(io_handle);
102 :
103 1 : return VSIFTellL(fp);
104 : }
105 :
106 : /************************************************************************/
107 : /* Read() */
108 : /************************************************************************/
109 :
110 4998 : uint64 VSI_IOInterface::Read(void *buffer, uint64 size, uint64 nmemb,
111 : void *io_handle) const
112 :
113 : {
114 4998 : VSILFILE *fp = reinterpret_cast<VSILFILE *>(io_handle);
115 :
116 4998 : errno = 0;
117 :
118 4998 : uint64 result = VSIFReadL(buffer, (size_t)size, (size_t)nmemb, fp);
119 :
120 4998 : if (errno != 0 && result == 0 && nmemb != 0)
121 0 : ThrowPCIDSKException("Read(%d): %s", static_cast<int>(size * nmemb),
122 : LastError());
123 :
124 4998 : return result;
125 : }
126 :
127 : /************************************************************************/
128 : /* Write() */
129 : /************************************************************************/
130 :
131 13330 : uint64 VSI_IOInterface::Write(const void *buffer, uint64 size, uint64 nmemb,
132 : void *io_handle) const
133 :
134 : {
135 13330 : VSILFILE *fp = reinterpret_cast<VSILFILE *>(io_handle);
136 :
137 13330 : errno = 0;
138 :
139 13330 : uint64 result = VSIFWriteL(buffer, static_cast<size_t>(size),
140 : static_cast<size_t>(nmemb), fp);
141 :
142 13330 : if (errno != 0 && result == 0 && nmemb != 0)
143 0 : ThrowPCIDSKException("Write(%d): %s", static_cast<int>(size * nmemb),
144 : LastError());
145 :
146 13330 : return result;
147 : }
148 :
149 : /************************************************************************/
150 : /* Eof() */
151 : /************************************************************************/
152 :
153 0 : int VSI_IOInterface::Eof(void *io_handle) const
154 :
155 : {
156 0 : return VSIFEofL(reinterpret_cast<VSILFILE *>(io_handle));
157 : }
158 :
159 : /************************************************************************/
160 : /* Flush() */
161 : /************************************************************************/
162 :
163 247 : int VSI_IOInterface::Flush(void *io_handle) const
164 :
165 : {
166 247 : return VSIFFlushL(reinterpret_cast<VSILFILE *>(io_handle));
167 : }
168 :
169 : /************************************************************************/
170 : /* Close() */
171 : /************************************************************************/
172 :
173 384 : int VSI_IOInterface::Close(void *io_handle) const
174 :
175 : {
176 384 : return VSIFCloseL(reinterpret_cast<VSILFILE *>(io_handle));
177 : }
178 :
179 : /************************************************************************/
180 : /* LastError() */
181 : /* */
182 : /* Return a string representation of the last error. */
183 : /************************************************************************/
184 :
185 5 : const char *VSI_IOInterface::LastError() const
186 :
187 : {
188 5 : return strerror(errno);
189 : }
190 :
191 : /************************************************************************/
192 : /* If we are using the internal copy of the PCIDSK SDK we need */
193 : /* to provide stub implementations of GetDefaultIOInterfaces() */
194 : /* and GetDefaultMutex() */
195 : /************************************************************************/
196 :
197 : #ifdef PCIDSK_INTERNAL
198 :
199 642 : const IOInterfaces *PCIDSK::GetDefaultIOInterfaces()
200 : {
201 642 : static VSI_IOInterface singleton_vsi_interface;
202 :
203 642 : return &singleton_vsi_interface;
204 : }
205 :
206 : /************************************************************************/
207 : /* CPLThreadMutex */
208 : /************************************************************************/
209 :
210 : class CPLThreadMutex final : public PCIDSK::Mutex
211 :
212 : {
213 : private:
214 : CPLMutex *hMutex;
215 :
216 : public:
217 : CPLThreadMutex();
218 : ~CPLThreadMutex() override;
219 :
220 : int Acquire(void) override;
221 : int Release(void) override;
222 : };
223 :
224 : /************************************************************************/
225 : /* CPLThreadMutex() */
226 : /************************************************************************/
227 :
228 306 : CPLThreadMutex::CPLThreadMutex()
229 :
230 : {
231 306 : hMutex = CPLCreateMutex();
232 306 : CPLReleaseMutex(hMutex); // it is created acquired, but we want it free.
233 306 : }
234 :
235 : /************************************************************************/
236 : /* ~CPLThreadMutex() */
237 : /************************************************************************/
238 :
239 612 : CPLThreadMutex::~CPLThreadMutex()
240 :
241 : {
242 306 : CPLDestroyMutex(hMutex);
243 612 : }
244 :
245 : /************************************************************************/
246 : /* Release() */
247 : /************************************************************************/
248 :
249 17916 : int CPLThreadMutex::Release()
250 :
251 : {
252 17916 : CPLReleaseMutex(hMutex);
253 17916 : return 1;
254 : }
255 :
256 : /************************************************************************/
257 : /* Acquire() */
258 : /************************************************************************/
259 :
260 17916 : int CPLThreadMutex::Acquire()
261 :
262 : {
263 17916 : return CPLAcquireMutex(hMutex, 100.0);
264 : }
265 :
266 : /************************************************************************/
267 : /* DefaultCreateMutex() */
268 : /************************************************************************/
269 :
270 306 : PCIDSK::Mutex *PCIDSK::DefaultCreateMutex(void)
271 :
272 : {
273 306 : return new CPLThreadMutex();
274 : }
275 :
276 : #endif /* def PCIDSK_INTERNAL */
|