Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: Arrow generic code 4 : * Purpose: Arrow generic code 5 : * Author: Even Rouault, <even.rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2022, Planet Labs 9 : * 10 : * Permission is hereby granted, free of charge, to any person obtaining a 11 : * copy of this software and associated documentation files (the "Software"), 12 : * to deal in the Software without restriction, including without limitation 13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 : * and/or sell copies of the Software, and to permit persons to whom the 15 : * Software is furnished to do so, subject to the following conditions: 16 : * 17 : * The above copyright notice and this permission notice shall be included 18 : * in all copies or substantial portions of the Software. 19 : * 20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 : * DEALINGS IN THE SOFTWARE. 27 : ****************************************************************************/ 28 : 29 : #ifndef OGR_ARROW_RANDOM_ACCESS_FILE_H 30 : #define OGR_ARROW_RANDOM_ACCESS_FILE_H 31 : 32 : #include "cpl_vsi.h" 33 : #include "cpl_vsi_virtual.h" 34 : 35 : #include "arrow/buffer.h" 36 : #include "arrow/io/file.h" 37 : #include "arrow/io/interfaces.h" 38 : 39 : /************************************************************************/ 40 : /* OGRArrowRandomAccessFile */ 41 : /************************************************************************/ 42 : 43 : class OGRArrowRandomAccessFile final : public arrow::io::RandomAccessFile 44 : { 45 : int64_t m_nSize = -1; 46 : VSILFILE *m_fp; 47 : bool m_bOwnFP; 48 : 49 : OGRArrowRandomAccessFile(const OGRArrowRandomAccessFile &) = delete; 50 : OGRArrowRandomAccessFile & 51 : operator=(const OGRArrowRandomAccessFile &) = delete; 52 : 53 : public: 54 5 : explicit OGRArrowRandomAccessFile(VSILFILE *fp, bool bOwnFP) 55 5 : : m_fp(fp), m_bOwnFP(bOwnFP) 56 : { 57 5 : } 58 : 59 607 : explicit OGRArrowRandomAccessFile(VSIVirtualHandleUniquePtr &&fp) 60 607 : : m_fp(fp.release()), m_bOwnFP(true) 61 : { 62 607 : } 63 : 64 612 : ~OGRArrowRandomAccessFile() override 65 612 : { 66 612 : if (m_fp && m_bOwnFP) 67 607 : VSIFCloseL(m_fp); 68 612 : } 69 : 70 0 : arrow::Status Close() override 71 : { 72 0 : if (!m_bOwnFP) 73 : return arrow::Status::IOError( 74 0 : "Cannot close a file that we don't own"); 75 0 : int ret = VSIFCloseL(m_fp); 76 0 : m_fp = nullptr; 77 : return ret == 0 ? arrow::Status::OK() 78 0 : : arrow::Status::IOError("Error while closing"); 79 : } 80 : 81 0 : arrow::Result<int64_t> Tell() const override 82 : { 83 0 : return static_cast<int64_t>(VSIFTellL(m_fp)); 84 : } 85 : 86 0 : bool closed() const override 87 : { 88 0 : return m_fp == nullptr; 89 : } 90 : 91 1684 : arrow::Status Seek(int64_t position) override 92 : { 93 1684 : if (VSIFSeekL(m_fp, static_cast<vsi_l_offset>(position), SEEK_SET) == 0) 94 1684 : return arrow::Status::OK(); 95 0 : return arrow::Status::IOError("Error while seeking"); 96 : } 97 : 98 1732 : arrow::Result<int64_t> Read(int64_t nbytes, void *out) override 99 : { 100 : CPLAssert(static_cast<int64_t>(static_cast<size_t>(nbytes)) == nbytes); 101 1732 : return static_cast<int64_t>( 102 1732 : VSIFReadL(out, 1, static_cast<size_t>(nbytes), m_fp)); 103 : } 104 : 105 1702 : arrow::Result<std::shared_ptr<arrow::Buffer>> Read(int64_t nbytes) override 106 : { 107 : // CPLDebug("ARROW", "Reading %d bytes", int(nbytes)); 108 : // Ugly hack for https://github.com/OSGeo/gdal/issues/9497 109 1702 : if (CPLGetConfigOption("OGR_ARROW_STOP_IO", nullptr)) 110 : { 111 0 : return arrow::Result<std::shared_ptr<arrow::Buffer>>(); 112 : } 113 3404 : auto buffer = arrow::AllocateResizableBuffer(nbytes); 114 1702 : if (!buffer.ok()) 115 : { 116 0 : return buffer; 117 : } 118 1702 : uint8_t *buffer_data = (*buffer)->mutable_data(); 119 3404 : auto nread = Read(nbytes, buffer_data); 120 1702 : CPL_IGNORE_RET_VAL( 121 3404 : (*buffer)->Resize(*nread)); // shrink --> cannot fail 122 1702 : return buffer; 123 : } 124 : 125 604 : arrow::Result<int64_t> GetSize() override 126 : { 127 604 : if (m_nSize < 0) 128 : { 129 604 : const auto nPos = VSIFTellL(m_fp); 130 604 : VSIFSeekL(m_fp, 0, SEEK_END); 131 604 : m_nSize = static_cast<int64_t>(VSIFTellL(m_fp)); 132 604 : VSIFSeekL(m_fp, nPos, SEEK_SET); 133 : } 134 604 : return m_nSize; 135 : } 136 : }; 137 : 138 : #endif // OGR_ARROW_RANDOM_ACCESS_FILE_H