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