PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
PEBLPath.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/utility/PEBLPath.cpp
4// Purpose: Utility class storing search path and searching for files there
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
28#ifdef PEBL_WIN32
29#include <winsock2.h> // Must be first to avoid conflicts
30#endif
31
32#include "PEBLPath.h"
33#include "../base/Variant.h"
34#include "PError.h"
35#include "BinReloc.h"
36#include "PEBLUtility.h"
37#include <sys/stat.h>
38#include <list>
39#include <string>
40#include <iostream>
41
42using std::endl;
43using std::string;
44using std::ostream;
45using std::cout;
46
47
48#ifdef PEBL_OSX
49#include <mach-o/dyld.h> /* _NSGetExecutablePath */
50#include <CoreFoundation/CFBundle.h>
51#elif defined(PEBL_WIN32)
52#include <windows.h>
53#endif
54
58
59
60void PEBLPath::Initialize(std::list<std::string> files)
61{
62 // std::cout << "Initializing path\n";
63
64
65//cout << "STarting peblpath\n";
66#if defined( PEBL_LINUX)
67
68 //cout << "***********linux\n";
69 //On unix, add the following paths:
70 //current working directory,
71 AddToPathList("./");
72
73 //Look for absolute pathnames
74 AddToPathList("");
75 //The directories of each file on the command-line.
76 string tmp;
77 std::list<string>::iterator i=files.begin();
78 i++; //skip over the command name in UNIX.
79 while(i != files.end())
80 {
81 //For each commandline argument, strip the filename and add it.
82 tmp = PEBLUtility::StripFile(*i);
83 if(tmp != "")
84 {
85 AddToPathList(tmp);
86 }
87 i++;
88 }
89
90
91#ifdef EXECNAME
92#define OP OP2(EXECNAME)
93#define OP2(x) OP3(x)
94#define OP3(a) #a
95
96 string peblname = OP;
97#else
98 string peblname ="pebl2";
99#endif
100
101 string basedir = "";
102
103 //Initialize the binreloc library (courtesy of autopackage).
104 BrInitError error;
105 if (br_init (&error) == 0 && error != BR_INIT_ERROR_DISABLED)
106 {
107 PError::SignalWarning("Warning: BinReloc failed to initialize.\n Will fallback to current directory.\n");
108 basedir = "./";
109 } else {
110
111 std::cerr << "Executable file located at: [" << br_find_exe("") << "].\n";
112
113 // Get directory containing the executable
114 char* exe_dir = br_find_exe_dir("");
115 if (exe_dir != NULL) {
116 // Go up one level from bin/ to get base directory
117 basedir = string(exe_dir) + string("/../");
118 std::cerr << "Executable directory: [" << exe_dir << "]\n";
119 std::cerr << "Base resources found at: [" << basedir << "]\n";
120 free(exe_dir);
121 } else {
122 // Fallback to current directory
123 basedir = "./";
124 std::cerr << "Using current directory as base.\n";
125 }
126 }
127
128
129
130 //media subdirectories of execution directory.
131 //fonts
132 AddToPathList(MergePathAndFile(basedir, "media/fonts/"));
133
134 //Sounds
135 AddToPathList(MergePathAndFile(basedir, "media/sounds/"));
136
137 //images
138 AddToPathList(MergePathAndFile(basedir, "media/images/"));
139
140 //text
141 AddToPathList(MergePathAndFile(basedir, "media/text/"));
142
143 //css
144 AddToPathList(MergePathAndFile(basedir, "media/css/"));
145
146 //settings
147 AddToPathList(MergePathAndFile(basedir, "media/settings/"));
148
149 //library functions
150 AddToPathList(MergePathAndFile(basedir, "pebl-lib/"));
151#elif defined (PEBL_EMSCRIPTEN)
152
153
154 AddToPathList("./");
155
156
157 //Look for absolute pathnames
158 AddToPathList("");
159 //The directories of each file on the command-line.
160 string tmp;
161 std::list<string>::iterator i=files.begin();
162 i++; //skip over the command name in UNIX.
163 while(i != files.end())
164 {
165 //For each commandline argument, strip the filename and add it.
166 tmp = PEBLUtility::StripFile(*i);
167 if(tmp != "")
168 {
169 AddToPathList(tmp);
170 }
171 i++;
172 }
173
174
175 //in emscripten, everything goes in the root of the base directory.
176 string basedir = "/usr/local/share/pebl2/";
177
178 //Add a blank root directory, but just for emscripten.
179 AddToPathList("");
180
181 //media subdirectories of execution directory.
182 //fonts
183 AddToPathList(MergePathAndFile(basedir, "media/fonts/"));
184
185 //Sounds
186 AddToPathList(MergePathAndFile(basedir, "media/sounds/"));
187
188 //images
189 AddToPathList(MergePathAndFile(basedir, "media/images/"));
190
191 //text
192 AddToPathList(MergePathAndFile(basedir, "media/text/"));
193
194 //css
195 AddToPathList(MergePathAndFile(basedir, "media/css/"));
196
197 //settings
198 AddToPathList(MergePathAndFile(basedir, "media/settings/"));
199
200 //library functions
201 AddToPathList(MergePathAndFile(basedir, "pebl-lib/"));
202
203
204#elif defined PEBL_OSX
205
206
207 //cout << "***********OSX\n";
208
209
210 // ----------------------------------------------------------------------------
211 // This makes relative paths work in C++ in Xcode by changing directory to the
212 // Resources folder inside the .app bundle
213 CFBundleRef mainBundle = CFBundleGetMainBundle();
214 CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
215 char path[PATH_MAX];
216 if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
217 {
218 PError::SignalFatalError("Unable to identify resource location.\n");// error!
219 }
220 CFRelease(resourcesURL);
221
222 std::string basedir = (std::string)path + "/";
223
224
225 //On OSX, we will keep the things in the Resources/ subdirectory inside the application bundle
226 //current working directory,
227 AddToPathList("./");
228
229 //Look for absolute pathnames
230 AddToPathList("");
231 //The directories of each file on the command-line.
232 string tmp;
233 std::list<string>::iterator i=files.begin();
234 i++; //skip over the command name in UNIX.
235 while(i != files.end())
236 {
237 //For each commandline argument, strip the filename and add it.
238 tmp = PEBLUtility::StripFile(*i);
239 if(tmp != "")
240 {
241 AddToPathList(tmp);
242 }
243 i++;
244 }
245
246
247// _NSGetExecutablePath( pathbuf, (uint32_t*)(&bufsize));
248// cout << "OSX name: " << pathbuf << endl;
249
250// string prefix = br_find_prefix("");
251// basedir = prefix + string("Resources/");
252
253
254 //On OSX, we will keep the things in the Resources/ subdirectory inside the application bundle
255
256
257 //media subdirectories of execution directory.
258 //fonts
259 AddToPathList(MergePathAndFile(basedir, "media/fonts/"));
260
261 //Sounds
262 AddToPathList(MergePathAndFile(basedir, "media/sounds/"));
263
264 //images
265 AddToPathList(MergePathAndFile(basedir, "media/images/"));
266
267 //text
268 AddToPathList(MergePathAndFile(basedir, "media/text/"));
269
270 //css
271 AddToPathList(MergePathAndFile(basedir, "media/css/"));
272
273 //settings
274 AddToPathList(MergePathAndFile(basedir, "media/settings/"));
275
276 //library functions
277 AddToPathList(MergePathAndFile(basedir, "pebl-lib/"));
278
279
280/*#elif defined(PEBL_WIN32) or defined(WIN32)*/
281#else
282
283 string basedir = "";
284
285 TCHAR szPath[MAX_PATH];
286
287 if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
288 {
289
290 //fallback calculation here szPath = "fallback";
291 }
292
293// cout << "PATH:" << szPath << endl;
294 basedir = PEBLUtility::StripFile(szPath) + "..\\";
295//cout << "***********************\n";
296 //On Windows add the following paths:
297
298 //current working directory
299 AddToPathList(".\\");
300
301
302 //Absolute Pathnames
303 AddToPathList(basedir);
304
305
306
307 AddToPathList("");
308
309 //The directories of each file on the command-line.
310 // files[0] is the execution directory,
311 // the others are filenames.
312 string tmp;
313 std::list<string>::iterator i=files.begin();
314 while(i != files.end())
315 {
316 //For each commandline argument, strip the filename and add it.
317 tmp = PEBLUtility::StripFile(*i);
318 if(tmp != "")
319 {
320 AddToPathList(tmp);
321 }
322 i++;
323 }
324
325
326 //media subdirectories of execution directory.
327 //fonts
328 AddToPathList(MergePathAndFile(basedir, "media\\fonts\\"));
329
330 //Audio
331 AddToPathList(MergePathAndFile(basedir, "media\\sounds\\"));
332
333 //images
334 AddToPathList(MergePathAndFile(basedir, "media\\images\\"));
335
336 //Text files
337 AddToPathList(MergePathAndFile(basedir, "media\\text\\"));
338
339 //CSS files
340 AddToPathList(MergePathAndFile(basedir, "media\\css\\"));
341
342 //Settings files
343 AddToPathList(MergePathAndFile(basedir, "media\\settings\\"));
344
345 //PEBL Library functions
346 AddToPathList(MergePathAndFile(basedir, "pebl-lib\\"));
347
348
349#endif
350
351
352}
353
355{
356 mPathList.clear();
357}
358
359
360//Note: paths should be added with a '/' afterwards
361void PEBLPath::AddToPathList(const string & pathname)
362{
363
364 mPathList.push_back(pathname);
365}
366
367
368string PEBLPath::FindFile(const string & filename)
369{
370 // cout << "Ylooking for file" << filename << endl;
371
372
373 struct stat st;
374
375 unsigned long int lengthp;
376 unsigned long int lengthfilename;
377 string tmp;
378 std::list<string>::const_iterator p = mPathList.begin();
379
380 while(p != mPathList.end())
381 {
382 lengthp = (*p).size();
383 lengthfilename = filename.size();
384
385 tmp = (*p) + filename;
386
387
388 //Check to see if the file exists.
389 //cout << "Checking:" << tmp.c_str() <<":"<< stat(tmp.c_str(), &st)<< endl;
390 if(stat(tmp.c_str(), &st)==0)
391 {
392 //The file exists, so return it
393 return tmp;
394 }
395
396 //otherwise, increment and try again.
397 p++;
398 }
399 //If everything fails, return "".
400 return "";
401}
402
403
404
405const string PEBLPath::MergePathAndFile(const string & path, const string & file)
406{
407 return path + file;
408}
409
410
411bool PEBLPath::IsDirectory(const string & pathname)
412{
413#if defined PEBL_UNIX
414 char separator = '/';
415#elif defined PEBL_WIN32
416 char separator = '\\';
417#elif defined WIN32
418 char separator = '\\';
419#elif defined PEBL_EMSCRIPTEN
420 char separator = '/';
421#endif
422
423
424 //This may not be the best way to do it; we maybe
425 //should check to see using OS library calls.
426 if(pathname[pathname.size()-1] == separator)
427 return true;
428 else
429 return false;
430
431}
432
433
434ostream & PEBLPath::Print(ostream & out) const
435{
436
437 out << "--------------------------------------\n";
438 out << "Path List:\n";
439 std::list<string>::const_iterator p = mPathList.begin();
440 while(p != mPathList.end())
441 {
442 out << *p << endl;
443 p++;
444 }
445
446 out << "--------------------------------------\n";
447 return out;
448}
449
450ostream & operator << (ostream & out, const PEBLPath & path)
451{
452 return path.Print(out);
453
454}
#define NULL
Definition BinReloc.cpp:317
int br_init(BrInitError *error)
Definition BinReloc.cpp:338
char * br_find_exe_dir(const char *default_dir)
Definition BinReloc.cpp:405
char * br_find_exe(const char *default_exe)
Definition BinReloc.cpp:377
BrInitError
Definition BinReloc.h:22
@ BR_INIT_ERROR_DISABLED
Definition BinReloc.h:32
ostream & operator<<(ostream &out, const PEBLPath &path)
Definition PEBLPath.cpp:450
const string MergePathAndFile(const string &path, const string &file)
Definition PEBLPath.cpp:405
std::string FindFile(const string &filename)
Definition PEBLPath.cpp:368
void AddToPathList(const string &s)
Definition PEBLPath.cpp:361
std::ostream & Print(std::ostream &out) const
Definition PEBLPath.cpp:434
void Initialize(std::list< std::string >)
Definition PEBLPath.cpp:60
bool IsDirectory(const string &pathname)
Definition PEBLPath.cpp:411
const std::string StripFile(const std::string &file)
void SignalWarning(const std::string &message)
Definition PError.cpp:119
void SignalFatalError(const std::string &message)