1 // Copyright 2021 Jean Pierre Cimalando
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // SPDX-License-Identifier: Apache-2.0
26 #if defined(__APPLE__)
29 #if !defined(_WIN32) && !defined(__FreeBSD__)
35 #if defined(YSFX_NO_STANDARD_MUTEX)
36 # include "WDL/mutex.h"
41 YSFX_DEFINE_AUTO_PTR(FILE_u
, FILE, fclose
);
43 FILE *fopen_utf8(const char *path
, const char *mode
);
44 int64_t fseek_lfs(FILE *stream
, int64_t off
, int whence
);
45 int64_t ftell_lfs(FILE *stream
);
47 //------------------------------------------------------------------------------
50 using c_locale_t
= locale_t
;
52 using c_locale_t
= _locale_t
;
55 c_locale_t
c_numeric_locale();
57 //------------------------------------------------------------------------------
60 # define ysfx_alloca(n) alloca((n))
62 # define ysfx_alloca(n) _malloca((n))
65 //------------------------------------------------------------------------------
67 #if !defined(YSFX_NO_STANDARD_MUTEX)
68 using mutex
= std::mutex
;
73 void lock() { m_mutex
.Enter(); }
74 void unlock() { m_mutex
.Leave(); }
81 //------------------------------------------------------------------------------
83 using string_list
= std::vector
<std::string
>;
85 double c_atof(const char *text
, c_locale_t loc
);
86 double c_strtod(const char *text
, char **endp
, c_locale_t loc
);
87 double dot_atof(const char *text
);
88 double dot_strtod(const char *text
, char **endp
);
89 bool ascii_isspace(char c
);
90 bool ascii_isalpha(char c
);
91 char ascii_tolower(char c
);
92 char ascii_toupper(char c
);
93 int ascii_casecmp(const char *a
, const char *b
);
94 uint32_t latin1_toupper(uint32_t c
);
95 uint32_t latin1_tolower(uint32_t c
);
96 char *strdup_using_new(const char *src
);
97 string_list
split_strings_noempty(const char *input
, bool(*pred
)(char));
98 std::string
trim(const char *input
, bool(*pred
)(char));
100 //------------------------------------------------------------------------------
102 void pack_u32le(uint32_t value
, uint8_t data
[4]);
103 void pack_f32le(float value
, uint8_t data
[4]);
104 uint32_t unpack_u32le(const uint8_t data
[4]);
105 float unpack_f32le(const uint8_t data
[4]);
107 //------------------------------------------------------------------------------
109 std::vector
<uint8_t> decode_base64(const char *text
, size_t len
= ~(size_t)0);
110 std::string
encode_base64(const uint8_t *data
, size_t len
);
112 //------------------------------------------------------------------------------
114 using file_uid
= std::pair
<uint64_t, uint64_t>;
115 bool get_file_uid(const char *path
, file_uid
&uid
);
116 bool get_stream_file_uid(FILE *stream
, file_uid
&uid
);
117 bool get_descriptor_file_uid(int fd
, file_uid
&uid
);
119 bool get_handle_file_uid(void *handle
, file_uid
&uid
);
122 //------------------------------------------------------------------------------
124 struct split_path_t
{
130 // check if the character is a path separator
131 bool is_path_separator(char ch
);
132 // break down a path into individual components
133 split_path_t
split_path(const char *path
);
134 // get the file name part (all after the final '/' separator)
135 std::string
path_file_name(const char *path
);
136 // get the directory part (all up to the '/' separator, inclusive)
137 std::string
path_directory(const char *path
);
138 // add the final '/' separator if absent; if empty, does nothing
139 std::string
path_ensure_final_separator(const char *path
);
140 // compare the tail of the path with the suffix, case-insensitively
141 bool path_has_suffix(const char *path
, const char *suffix
);
142 // check whether the path is relative
143 bool path_is_relative(const char *path
);
145 //------------------------------------------------------------------------------
147 // check whether a file exists on disk
148 bool exists(const char *path
);
149 // list the elements of a directory; directories are distinguished with a final '/'
150 string_list
list_directory(const char *path
);
151 // visit the root and subdirectories in depth-first order
152 void visit_directories(const char *rootpath
, bool (*visit
)(const std::string
&, void *), void *data
);
153 // resolve a path which matches root/fragment, where fragment is case-insensitive (0=failed, 1=exact, 2=inexact)
154 int case_resolve(const char *root
, const char *fragment
, std::string
&result
);
156 //------------------------------------------------------------------------------
159 std::wstring
widen(const std::string
&u8str
);
160 std::wstring
widen(const char *u8data
, size_t u8len
= ~(size_t)0);
161 std::string
narrow(const std::wstring
&wstr
);
162 std::string
narrow(const wchar_t *wdata
, size_t wlen
= ~(size_t)0);
165 //------------------------------------------------------------------------------
170 explicit scope_guard(F
&&f
) : f(std::forward
<F
>(f
)), a(true) {}
171 scope_guard(scope_guard
&&o
) : f(std::move(o
.f
)), a(o
.a
) { o
.a
= false; }
172 ~scope_guard() { if (a
) f(); }
173 void disarm() { a
= false; }
177 scope_guard(const scope_guard
&) = delete;
178 scope_guard
&operator=(const scope_guard
&) = delete;
181 template <class F
> scope_guard
<F
> defer(F
&&f
)
183 return scope_guard
<F
>(std::forward
<F
>(f
));