comparison foosdk/sdk/foobar2000/shared/shared-nix.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #include "shared.h"
2 #include <dirent.h>
3 #include <pfc/wildcard.h>
4 #include <unistd.h>
5
6 // foobar2000 SDK project method... bah
7 namespace foobar2000_io {
8 PFC_NORETURN void nix_io_op_fail();
9 }
10 using namespace foobar2000_io;
11
12 namespace {
13 class uFindFileImpl : public uFindFile {
14 public:
15 uFindFileImpl ( DIR * dir ) : m_dir(dir) {}
16 bool FindNext() override {
17 m_entry = readdir(m_dir);
18 return m_entry != NULL;
19 }
20 const char * GetFileName() override {
21 return m_entry->d_name;
22 }
23 bool IsDirectory() override {
24 return m_entry->d_type == DT_DIR;
25 }
26 ~uFindFileImpl() {
27 closedir(m_dir);
28 }
29 private:
30 dirent * m_entry;
31
32 DIR * m_dir;
33 };
34
35 class uFindFileFiltered : public uFindFile {
36 public:
37 uFindFileFiltered( DIR * dir, const char * wc ) : m_impl(dir), m_wc(wc) {}
38 bool FindNext() override {
39 for( ;; ) {
40 if (!m_impl.FindNext()) return false;
41 if ( testWC() ) return true;
42 }
43 }
44 const char * GetFileName() override {
45 return m_impl.GetFileName();
46 }
47 bool IsDirectory() override {
48 return m_impl.IsDirectory();
49 }
50 bool testWC() {
51 return wildcard_helper::test(GetFileName(), m_wc);
52 }
53
54 uFindFileImpl m_impl;
55 const pfc::string8 m_wc;
56 };
57 }
58
59 puFindFile uFindFirstFile(const char * path) {
60
61 if ( wildcard_helper::has_wildcards( path ) ) {
62 size_t idx = pfc::scan_filename(path);
63
64 try {
65 DIR * dir = opendir( pfc::string8(path, idx) );
66 if (dir == NULL) nix_io_op_fail();
67 try {
68 uFindFile * ff;
69 try {
70 ff = new uFindFileFiltered(dir, path + idx);
71 } catch(...) { closedir( dir ); throw; }
72 if (ff->FindNext()) return ff;
73 delete ff;
74 return NULL;
75 } catch(...) { closedir( dir ); throw; }
76 } catch(...) {return NULL;}
77
78 }
79
80 try {
81 DIR * dir = opendir( path );
82 if (dir == NULL) nix_io_op_fail();
83 try {
84 uFindFile * ff;
85 try {
86 ff = new uFindFileImpl(dir);
87 } catch(...) { closedir( dir ); throw; }
88 if (ff->FindNext()) return ff;
89 delete ff;
90 return NULL;
91 } catch(...) { closedir( dir ); throw; }
92 } catch(...) {return NULL;}
93 }
94
95 pfc::string8 uStringPrintf(const char * fmt, ...) {
96 pfc::string8 ret;
97 va_list list;
98 va_start(list,fmt);
99 uPrintfV(ret,fmt,list);
100 va_end(list);
101 return ret;
102 }
103
104 void uPrintfV(pfc::string_base & out,const char * fmt,va_list arglist) {
105 pfc::string_printf_here_va(out, fmt, arglist);
106 }
107
108 void uPrintf(pfc::string_base & out,const char * fmt,...) {
109 va_list list;va_start(list,fmt);uPrintfV(out,fmt,list);va_end(list);
110 }
111
112
113 static int makeInfiniteWaitEvent() {
114 int fdPipe[2];
115 pfc::createPipe(fdPipe);
116 return fdPipe[0]; // leak the other end
117 }
118
119 int GetInfiniteWaitEvent() {
120 static int obj = makeInfiniteWaitEvent();
121 return obj;
122 }
123
124
125 // DUMMY
126 void SHARED_EXPORT uAddPanicHandler(fb2k::panicHandler*) {
127
128 }
129 void SHARED_EXPORT uRemovePanicHandler(fb2k::panicHandler*) {
130
131 }
132
133 void SHARED_EXPORT uOutputDebugString(const char * msg) {
134 // UGLY: underlying APIs want whole lines, calling code feeds lines terminated with \n or \r\n because Windows
135 pfc::string8 temp ( msg );
136 if ( temp.endsWith('\n') ) temp.truncate( temp.length() - 1) ;
137 if ( temp.endsWith('\r') ) temp.truncate( temp.length() - 1) ;
138 pfc::outputDebugLine(temp);
139 }
140 namespace pfc { PFC_NORETURN void crashImpl(); }
141 PFC_NORETURN void SHARED_EXPORT uBugCheck() {
142 pfc::crashImpl();
143 }
144
145 int SHARED_EXPORT uStringCompare(const char * elem1, const char * elem2) {
146 return pfc::naturalSortCompareI(elem1, elem2);
147 }
148
149 void fb2kDebugSelfTest() {
150
151 }
152
153 bool uGetTempPath(pfc::string_base & out) {
154 auto var = getenv("TMPDIR");
155 if ( var == nullptr ) uBugCheck();
156 out = var;
157 return true;
158 }
159 bool uGetTempFileName(const char * path_name,const char * prefix,unsigned unique,pfc::string_base & out) {
160 #if 0 // sample use
161 pfc::string8 temp_path, temp_file;
162 uGetTempPath(temp_path);
163 uGetTempFileName(temp_path, "img", 0, temp_file);
164 #endif
165 pfc::string8 ret;
166 if ( path_name == nullptr ) uGetTempPath( ret );
167 else ret = path_name;
168
169 pfc::chain_list_v2_t<pfc::string8> segments;
170 if ( prefix ) segments += prefix;
171 if ( unique ) segments += pfc::format(unique);
172 segments += pfc::print_guid(pfc::createGUID());
173
174 pfc::string8 fn;
175 for( auto & seg : segments ) {
176 if (seg.length() == 0) continue;
177 if ( fn.length() > 0 ) fn += "-";
178 fn += seg;
179 }
180
181 ret.add_filename( fn );
182 out = ret;
183 return true;
184 }
185
186 pfc::string8 uGetTempFileName() {
187 pfc::string8 ret;
188 uGetTempFileName(nullptr, nullptr, 0, ret);
189 return ret;
190 }
191
192
193 void fb2k::crashWithMessage [[noreturn]] ( const char * msg_ ) {
194 uAddDebugEvent( msg_ );
195 pfc::crashWithMessageOnStack(msg_);
196 }
197
198 bool uSetCurrentDirectory(const char * path) {
199 return chdir(path) == 0;
200 }
201 bool uGetCurrentDirectory(pfc::string_base & out) {
202 pfc::array_t<char> work;
203 work.resize( PATH_MAX );
204 for(;;) {
205 errno = 0;
206 if ( getcwd(work.get_ptr(), work.size()) != nullptr ) {
207 out = work.get_ptr(); return true;
208 }
209 if ( errno != ENAMETOOLONG ) return false;
210 work.resize( work.size() * 2 );
211 }
212 }