Blender V5.0
ply_import_buffer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BLI_fileops.h"
8
9#include <algorithm>
10#include <cstdio>
11#include <cstring>
12#include <stdexcept>
13
14static inline bool is_newline(char ch)
15{
16 return ch == '\n';
17}
18
19namespace blender::io::ply {
20
21PlyReadBuffer::PlyReadBuffer(const char *file_path, size_t read_buffer_size)
22 : buffer_(read_buffer_size), read_buffer_size_(read_buffer_size)
23{
24 file_ = BLI_fopen(file_path, "rb");
25}
26
28{
29 if (file_ != nullptr) {
30 fclose(file_);
31 }
32}
33
34void PlyReadBuffer::after_header(bool is_binary)
35{
36 is_binary_ = is_binary;
37}
38
40{
41 if (is_binary_) {
42 throw std::runtime_error("PLY read_line should not be used in binary mode");
43 }
44 if (pos_ >= last_newline_) {
45 refill_buffer();
46 }
47 BLI_assert(last_newline_ <= buffer_.size());
48 int res_begin = pos_;
49 while (pos_ < last_newline_ && !is_newline(buffer_[pos_])) {
50 pos_++;
51 }
52 int res_end = pos_;
53 /* Remove possible trailing CR from the result. */
54 if (res_end > res_begin && buffer_[res_end - 1] == '\r') {
55 --res_end;
56 }
57 /* Move cursor past newline. */
58 if (pos_ < buf_used_ && is_newline(buffer_[pos_])) {
59 pos_++;
60 }
61 return Span<char>(buffer_.data() + res_begin, res_end - res_begin);
62}
63
64bool PlyReadBuffer::read_bytes(void *dst, size_t size)
65{
66 while (size > 0) {
67 if (pos_ + size > buf_used_) {
68 if (!refill_buffer()) {
69 return false;
70 }
71 }
72 int to_copy = int(size);
73 to_copy = std::min(to_copy, buf_used_);
74 memcpy(dst, buffer_.data() + pos_, to_copy);
75 pos_ += to_copy;
76 dst = (char *)dst + to_copy;
77 size -= to_copy;
78 }
79 return true;
80}
81
82bool PlyReadBuffer::refill_buffer()
83{
84 BLI_assert(pos_ <= buf_used_);
85 BLI_assert(pos_ <= buffer_.size());
86 BLI_assert(buf_used_ <= buffer_.size());
87
88 if (file_ == nullptr || at_eof_) {
89 return false; /* File is fully read. */
90 }
91
92 /* Move any leftover to start of buffer. */
93 int keep = buf_used_ - pos_;
94 if (keep > 0) {
95 memmove(buffer_.data(), buffer_.data() + pos_, keep);
96 }
97 /* Read in data from the file. */
98 size_t read = fread(buffer_.data() + keep, 1, read_buffer_size_ - keep, file_) + keep;
99 at_eof_ = read < read_buffer_size_;
100 pos_ = 0;
101 buf_used_ = int(read);
102
103 /* Skip past newlines at the front of the buffer and find last newline. */
104 if (!is_binary_) {
105 while (pos_ < buf_used_ && is_newline(buffer_[pos_])) {
106 pos_++;
107 }
108
109 int last_nl = buf_used_;
110 if (!at_eof_) {
111 while (last_nl > 0) {
112 --last_nl;
113 if (is_newline(buffer_[last_nl])) {
114 break;
115 }
116 }
117 if (!is_newline(buffer_[last_nl])) {
118 /* Whole line did not fit into our read buffer. */
119 throw std::runtime_error("PLY text line did not fit into the read buffer");
120 }
121 }
122 last_newline_ = last_nl;
123 }
124
125 return true;
126}
127
128} // namespace blender::io::ply
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
Definition BLI_array.hh:256
const T * data() const
Definition BLI_array.hh:312
PlyReadBuffer(const char *file_path, size_t read_buffer_size=64 *1024)
bool read_bytes(void *dst, size_t size)
static bool is_newline(char ch)