1 #ifndef C4_YML_FILE_HPP_
2 #define C4_YML_FILE_HPP_
7 #ifndef C4_YML_ERROR_HPP_
17 C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996)
18 C4_SUPPRESS_WARNING_CLANG_WITH_PUSH("-Wdeprecated-declarations")
25 inline ScopedFILE(
const char *filename,
const char *access)
27 file = std::fopen(filename, access);
29 RYML_ERR_BASIC_(
"{}: could not open file", filename);
31 inline ~ScopedFILE() noexcept
35 ScopedFILE(
const ScopedFILE&) =
delete;
36 ScopedFILE( ScopedFILE&&) =
delete;
37 ScopedFILE& operator=(
const ScopedFILE&) =
delete;
38 ScopedFILE& operator=( ScopedFILE&&) =
delete;
57 inline void file_put_contents(
void const* buf,
size_t sz, FILE *file,
const char* filename=
nullptr)
59 size_t written = std::fwrite(buf, 1, sz, file);
60 if C4_UNLIKELY(written != sz)
61 RYML_ERR_BASIC_(
"{}: failed file write: expected={}B actual={}B", filename ? filename :
"file", sz, written);
65 template<
class ContiguousContainer>
66 void file_put_contents(ContiguousContainer
const& v, FILE *file,
const char *filename=
nullptr)
68 size_t vsz =
static_cast<size_t>(v.size()) *
sizeof(
typename ContiguousContainer::value_type);
69 void const* vbuf = v.empty() ?
nullptr : &v[0];
74 inline void file_put_contents(
void const* buf,
size_t sz,
const char *filename,
const char* access=
"wb")
76 detail::ScopedFILE f(filename, access);
81 template<
class ContiguousContainer>
82 void file_put_contents(ContiguousContainer
const& v,
const char *filename,
const char* access=
"wb")
84 size_t vsz =
static_cast<size_t>(v.size()) *
sizeof(
typename ContiguousContainer::value_type);
85 void const* vbuf = v.empty() ?
nullptr : &v[0];
106 inline void file_get_contents(
const char *filename, FILE *fp,
size_t filesz,
void *buf,
size_t bufsz)
108 RYML_ASSERT_BASIC_(filesz <= bufsz);(void)bufsz;
109 size_t read = std::fread(buf, 1, filesz, fp);
110 if C4_UNLIKELY(read != filesz)
111 RYML_ERR_BASIC_(
"{}: failed file read: expected={}B actual={}B", filename, filesz, read);
119 C4_NODISCARD
inline size_t file_get_contents(
const char *filename, FILE *fp,
void *buf,
size_t bufsz)
121 std::fseek(fp, 0, SEEK_END);
122 size_t filesz =
static_cast<size_t>(std::ftell(fp));
135 C4_NODISCARD
inline size_t file_get_contents(
const char *filename,
void *buf,
size_t bufsz,
const char *access=
"rb")
137 detail::ScopedFILE f(filename, access);
144 template<
class ContiguousContainer>
147 using value_type =
typename ContiguousContainer::value_type;
148 using size_type =
typename ContiguousContainer::size_type;
149 detail::ScopedFILE f(filename, access);
150 void * dat = !v->empty() ? &(*v)[0] :
nullptr;
151 size_t vsz =
static_cast<size_t>(v->size());
153 size_t num_elms = fsz /
sizeof(value_type);
154 if C4_UNLIKELY(fsz != num_elms *
sizeof(value_type))
155 RYML_ERR_BASIC_(
"{}: file size ({}B) not a multiple of element size ({}B)", filename, fsz,
sizeof(value_type));
156 v->resize(static_cast<size_type>(num_elms));
157 if(fsz > vsz *
sizeof(value_type))
164 template<
class ContiguousContainer>
167 ContiguousContainer cc;
192 template<
class ContiguousContainer>
195 using I =
typename ContiguousContainer::size_type;
196 using T =
typename ContiguousContainer::value_type;
200 I elmsz =
static_cast<I
>(
sizeof(T));
201 I sz = (num_bytes + elmsz - 1) / elmsz;
202 num_bytes = sz * elmsz;
204 unsigned char *buf =
reinterpret_cast<unsigned char*
>(&(*cont)[0]);
205 while((c = fgetc(f)) != EOF)
209 num_bytes = 2 * num_bytes;
210 if(num_bytes %
sizeof(T))
goto errsize;
211 cont->resize(num_bytes /
sizeof(T));
212 buf =
reinterpret_cast<unsigned char*
>(&(*cont)[0]);
214 buf[pos++] =
static_cast<unsigned char>(c);
218 cont->resize(pos /
sizeof(T));
221 RYML_ERR_BASIC_(
"file size is not multiple of element size");
226 template<
class ContiguousContainer>
229 ContiguousContainer cc;
236 C4_SUPPRESS_WARNING_CLANG_POP
237 C4_SUPPRESS_WARNING_MSVC_POP
void stdin_get_contents(ContiguousContainer *cont, FILE *f=stdin)
load a file from stdin (or similar stream-like file) and return a newly created ContiguousContainer w...
void file_get_contents(const char *filename, FILE *fp, size_t filesz, void *buf, size_t bufsz)
load a file of specified size from disk into an existing contiguous buffer.
Error utilities used by ryml.
ReadResult read(ConstNodeRef const &n, T *v)
void file_put_contents(void const *buf, size_t sz, FILE *file, const char *filename=nullptr)
save a contiguous buffer into a file