source: main/trunk/greenstone2/common-src/src/lib/fileutil.cpp@ 26653

Last change on this file since 26653 was 26653, checked in by davidb, 11 years ago

Code changed from using WIN32 use to _MSC_VER (the difference being the former is set for any Windows based compiler, whilst the latter is specifically set by a MicroSoft Visual Studio compiler). Up to this point the difference was not important, however to allow for cross-compilation (using mingw under Linux to produce native Windows binaries) the difference is imporant, and needs to be used more carefully

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/**********************************************************************
2 *
3 * fileutil.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "fileutil.h"
27
28#if defined(GSDL_USE_OBJECTSPACE)
29# include <ospace\std\iostream>
30# include <ospace\std\fstream>
31#elif defined(GSDL_USE_IOS_H)
32# include <iostream.h>
33# include <fstream.h>
34#else
35# include <iostream>
36# include <fstream>
37#endif
38
39
40// returns the proper concatenation of directory + directory/filename
41text_t filename_cat (text_t path1, text_t path2) {
42 text_t::iterator here;
43 text_t::iterator begin;
44 text_t::iterator end;
45
46 // make sure there is just one slash, of the correct type,
47 // at the end of path1 (unless path1 is an empty string).
48 if (!path1.empty()) {
49 // remove all trailing slashes
50 here = path1.end();
51 --here;
52 begin = path1.begin();
53 while (here != begin && (*here == '/' || *here == '\\')) {
54 --here;
55 }
56 ++here;
57 path1.erase(here,path1.end());
58
59 // add one final slash
60#ifdef __WIN32__
61 path1 += "\\";
62#else
63 path1 += "/";
64#endif
65 }
66
67 // remove all slashes from the start of path2
68 here = path2.begin();
69 end = path2.end();
70 while (here != end && (*here == '/' || *here == '\\')) {
71 ++here;
72 }
73 path2.erase (path2.begin(), here);
74
75 text_t fullpath = path1 + path2;
76
77 // make sure all the right slashes are used
78 here = fullpath.begin();
79 end = fullpath.end();
80 while (here != end) {
81#ifdef __WIN32__
82 if (*here == '/') *here = '\\';
83#else
84 if (*here == '\\') *here = '/';
85#endif
86 ++here ;
87 }
88 return fullpath;
89}
90
91text_t filename_cat (text_t path1, text_t path2, text_t path3) {
92 return filename_cat(filename_cat(path1,path2),path3);
93}
94
95text_t filename_cat (text_t path1, text_t path2, text_t path3, text_t path4) {
96 return filename_cat(filename_cat(filename_cat(path1,path2),path3),path4);
97}
98
99text_t filename_cat (text_t path1, text_t path2, text_t path3, text_t path4,
100 text_t path5) {
101 return filename_cat(filename_cat(filename_cat(filename_cat(path1,path2),path3),
102 path4),path5);
103}
104
105text_t filename_cat (text_t path1, text_t path2, text_t path3, text_t path4,
106 text_t path5, text_t path6) {
107 return filename_cat(filename_cat(path1,path2,path3,path4,path5),path6);
108}
109
110
111
112// returns the proper concatenation of the two paths, as in
113// /usr/bin:/usr/local/bin (for Unix) and c:\usr\bin;c:\usr\local\bin (for windows)
114
115text_t pathname_cat (text_t path1, text_t path2) {
116 text_t::iterator here;
117 text_t::iterator begin;
118 text_t::iterator end;
119
120 // make sure there are no slashes at the end of path1
121
122 if (!path1.empty()) {
123 // remove all trailing slashes
124 here = path1.end();
125 --here;
126 begin = path1.begin();
127 while (here != begin && (*here == '/' || *here == '\\')) {
128 --here;
129 }
130 ++here;
131 path1.erase(here,path1.end());
132
133 // add one final slash
134#ifdef __WIN32__
135 path1 += ";";
136#else
137 path1 += ":";
138#endif
139 }
140
141 // make sure there are no slashes at the end of path2
142 here = path2.end();
143 --here;
144 begin = path2.begin();
145 while (here != begin && (*here == '/' || *here == '\\')) {
146 --here;
147 }
148 ++here;
149 path2.erase (here, path2.end());
150
151 text_t fullpath = path1 + path2;
152
153 // make sure all the right slashes are used
154 here = fullpath.begin();
155 end = fullpath.end();
156 while (here != end) {
157#ifdef __WIN32__
158 if (*here == '/') *here = '\\';
159#else
160 if (*here == '\\') *here = '/';
161#endif
162 ++here ;
163 }
164 return fullpath;
165}
166
167text_t pathname_cat (text_t path1, text_t path2, text_t path3) {
168 return pathname_cat(pathname_cat(path1,path2),path3);
169}
170
171text_t pathname_cat (text_t path1, text_t path2, text_t path3, text_t path4) {
172 return pathname_cat(pathname_cat(pathname_cat(path1,path2),path3),path4);
173}
174
175text_t pathname_cat (text_t path1, text_t path2, text_t path3, text_t path4,
176 text_t path5) {
177 return pathname_cat(pathname_cat(pathname_cat(pathname_cat(path1,path2),path3),
178 path4),path5);
179}
180
181text_t pathname_cat (text_t path1, text_t path2, text_t path3, text_t path4,
182 text_t path5, text_t path6) {
183 return pathname_cat(pathname_cat(path1,path2,path3,path4,path5),path6);
184}
185
186
187
188
189
190// returns true if filename can be opened
191bool file_exists (const text_t &filename) {
192 char *cstr = filename.getcstr();
193#ifdef GSDL_USE_IOS_H
194 ifstream filestream (cstr, ios::in | ios::nocreate);
195#else
196 ifstream filestream (cstr, ios::in);
197#endif
198 delete []cstr;
199
200 if (filestream) {
201 // file exists
202 filestream.close ();
203 return true;
204 }
205
206 // file does not exist
207 return false;
208}
209
210// returns true if filename can be opened
211bool file_writable (const text_t &filename) {
212 char *cstr = filename.getcstr();
213#ifdef GSDL_USE_IOS_H
214 ifstream filestream (cstr, ios::out | ios::nocreate);
215#else
216 ifstream filestream (cstr, ios::out);
217#endif
218 delete []cstr;
219
220 if (filestream) {
221 // file exists
222 filestream.close ();
223 return true;
224 }
225
226 // file does not exist
227 return false;
228}
229
230#if defined(__WIN32__) && !defined(__GNUC__)
231
232#include <windows.h>
233
234bool directory_exists (const text_t &dirname) {
235
236 WIN32_FIND_DATA FileData;
237 HANDLE hSearch;
238
239 text_t dir = dirname + "\\*";
240 char *dirpath = dir.getcstr();
241
242 hSearch = FindFirstFile(dirpath, &FileData);
243 if (hSearch == INVALID_HANDLE_VALUE) {
244 delete []dirpath;
245 return false;
246 }
247
248 FindClose (hSearch);
249 delete []dirpath;
250 return true;
251}
252
253bool read_dir (const text_t &dirname, text_tset &filelist) {
254
255 WIN32_FIND_DATA FileData;
256 HANDLE hSearch;
257
258 text_t dir = dirname + "\\*";
259 char *dirpath = dir.getcstr();
260
261 hSearch = FindFirstFile(dirpath, &FileData);
262 if (hSearch == INVALID_HANDLE_VALUE) {
263 delete []dirpath;
264 return false;
265 }
266
267 text_t filename = FileData.cFileName;
268 if (filename != "." && filename != ".." && filename != "CVS" && filename != ".svn")
269 filelist.insert (filename);
270
271 while (FindNextFile(hSearch, &FileData)) {
272 filename = FileData.cFileName;
273 if (filename == "." || filename == ".." || filename == "CVS" || filename == ".svn")
274 continue;
275 filelist.insert (filename);
276 }
277
278 FindClose(hSearch);
279 delete []dirpath;
280
281 return true;
282}
283
284bool read_dir (const text_t &dirname, text_tarray &filelist) {
285
286 WIN32_FIND_DATA FileData;
287 HANDLE hSearch;
288
289 text_t dir = dirname + "\\*";
290 char *dirpath = dir.getcstr();
291
292 hSearch = FindFirstFile(dirpath, &FileData);
293 if (hSearch == INVALID_HANDLE_VALUE) {
294 delete []dirpath;
295 return false;
296 }
297
298 text_t filename = FileData.cFileName;
299 if (filename != "." && filename != ".." && filename != "CVS" && filename != ".svn")
300 filelist.push_back (filename);
301
302 while (FindNextFile(hSearch, &FileData)) {
303 filename = FileData.cFileName;
304 if (filename == "." || filename == ".." || filename == "CVS" || filename == ".svn")
305 continue;
306 filelist.push_back (filename);
307 }
308
309 FindClose(hSearch);
310 delete []dirpath;
311
312 return true;
313}
314
315#else
316
317#include <dirent.h>
318
319bool directory_exists (const text_t &dirname) {
320
321 char *tmp = dirname.getcstr();
322 DIR *dirin = opendir (tmp);
323 delete []tmp;
324
325 if (dirin == NULL) return false;
326 closedir (dirin);
327 return true;
328}
329
330bool read_dir (const text_t &dirname, text_tset &filelist) {
331
332 char *tmp = dirname.getcstr();
333 DIR *dirin = opendir (tmp);
334 delete []tmp;
335
336 if (dirin == NULL) return false;
337
338 dirent *dirp;
339
340 text_t filename;
341 while ((dirp = readdir (dirin)) != NULL) {
342 filename = dirp->d_name;
343 if (filename == "." || filename == ".." || filename == "CVS" || filename == ".svn")
344 continue;
345 filelist.insert (filename);
346 }
347 closedir (dirin);
348 return true;
349}
350
351bool read_dir (const text_t &dirname, text_tarray &filelist) {
352
353 char *tmp = dirname.getcstr();
354 DIR *dirin = opendir (tmp);
355 delete []tmp;
356
357 if (dirin == NULL) return false;
358
359 dirent *dirp;
360
361 text_t filename;
362 while ((dirp = readdir (dirin)) != NULL) {
363 filename = dirp->d_name;
364 if (filename == "." || filename == ".." || filename == "CVS" || filename == ".svn")
365 continue;
366 filelist.push_back (filename);
367 }
368 closedir (dirin);
369 return true;
370}
371
372#endif
373
374// returns true if things look like they happened ok
375bool file_copy (const text_t &fromfile, const text_t &tofile) {
376
377 char *fromfilec = fromfile.getcstr();
378 char *tofilec = tofile.getcstr();
379 bool fail = false;
380
381#ifdef _MSC_VER
382 // Use this block of code only for compilation under Windows
383 // with MS Visual Studio. Copilation under Windows with a compiler
384 // like minGW needs to go to the 'else' block
385
386 if (CopyFile (fromfilec, tofilec, FALSE) == 0) fail = true;
387
388#else
389
390 ifstream from (fromfilec);
391 if (!from) {
392 fail = true;
393 } else {
394 ofstream to (tofilec);
395 if (!to) {
396 fail = true;
397 from.close();
398 } else {
399 from >> to.rdbuf();
400 from.close();
401 to.close();
402 }
403 }
404
405#endif
406
407 delete []fromfilec;
408 delete []tofilec;
409 if (fail) return false;
410 return true;
411}
412
413// This is a fairly quick and nasty attempt at doing a "tail" on a file
414// (i.e. returning the last numlines lines of filename). It has one
415// important limitation in that it expects lines to be linelength
416// characters long on average. This of course makes it possible that it
417// won't return numlines lines if there are some lines that are longer than
418// linelength. It also makes it fairly inefficient as it always reads in
419// numlines*linelength characters when it most often doesn't need them all.
420// For current needs it's fine though.
421// -- Pass a linelength of 0 to use the default linelength (256 chars).
422// -- The maximum value of linelength is MAXLINELENGTH
423text_t file_tail (const text_t &filename, int numlines, int linelength) {
424
425#define MAXLINELENGTH 2048
426
427 if (numlines < 1) numlines = 1;
428 if (linelength < 1) linelength = 256;
429 if (linelength > MAXLINELENGTH) linelength = MAXLINELENGTH;
430
431 streampos numchars = linelength*numlines;
432
433 text_tarray lines;
434 text_t ret;
435
436 char *filenamec = filename.getcstr();
437 char linec[MAXLINELENGTH];
438 ifstream file_in (filenamec);
439 delete []filenamec;
440 if (file_in) {
441 file_in.seekg (0, ios::end);
442 streampos file_length = file_in.tellg();
443 if (file_length < numchars) numchars = file_length;
444 file_in.seekg (-numchars, ios::end);
445
446 while (!file_in.eof()) {
447 file_in.getline (linec, linelength);
448 ret.setcstr(linec);
449 text_t::const_iterator here = ret.begin();
450 text_t::const_iterator end = ret.end();
451 // make sure line has content
452 while (here != end) {
453 if (*here != '\n' && *here != ' ') {
454 lines.push_back (ret);
455 break;
456 }
457 ++here;
458 }
459 }
460 file_in.close();
461 }
462
463 ret.clear();
464 int numlinesgot = lines.size();
465 int sindex = 0;
466 if (numlinesgot > numlines) sindex = numlinesgot - numlines;
467 for (int i = sindex; i < numlinesgot; ++i) {
468 ret += lines[i] + "\n";
469 }
470
471 return ret;
472}
473
474#if defined(__WIN32__)
475
476#include <direct.h>
477// returns true if directory was created successfully
478bool mk_dir (const text_t &dirname) {
479 char *dirnamec = dirname.getcstr();
480 int rv = _mkdir (dirnamec);
481 delete []dirnamec;
482 if (rv == 0) return true;
483 return false;
484}
485
486#else
487
488#include <sys/stat.h>
489#include <sys/types.h>
490#include <fcntl.h>
491#include <unistd.h>
492// returns true if directory was created successfully
493bool mk_dir (const text_t &dirname) {
494 mode_t mode = 0777;
495 char *dirnamec = dirname.getcstr();
496 int rv = mkdir (dirnamec, mode);
497 delete []dirnamec;
498 if (rv == 0) return true;
499 return false;
500}
501
502#endif
503
504// read in file from filename and load into content
505bool read_file (const text_t &filename, text_t &content) {
506
507 content.clear();
508
509 char *filenamec = filename.getcstr();
510#ifdef GSDL_USE_IOS_H
511 ifstream file_in (filenamec, ios::in | ios::nocreate);
512#else
513 ifstream file_in (filenamec, ios::in);
514#endif
515 delete []filenamec;
516
517 if (file_in) {
518 char c;
519 file_in.get(c);
520 while (!file_in.eof ()) {
521 // Casting c to an unsigned char is vital when reading non-ASCII documents
522 content.push_back((unsigned char) c);
523 file_in.get(c);
524 }
525 file_in.close();
526 } else {
527 return false;
528 }
529 return true;
530}
Note: See TracBrowser for help on using the repository browser.