1*c2c66affSColin Finck // File.cpp
2*c2c66affSColin Finck // This file is (C) 2002-2003 Royce Mitchell III and released under the BSD license
3*c2c66affSColin Finck 
4*c2c66affSColin Finck #ifdef _MSC_VER
5*c2c66affSColin Finck #pragma warning ( disable : 4786 )
6*c2c66affSColin Finck #endif//_MSC_VER
7*c2c66affSColin Finck 
8*c2c66affSColin Finck #include "File.h"
9*c2c66affSColin Finck 
open(const char * filename,const char * mode)10*c2c66affSColin Finck bool File::open ( const char* filename, const char* mode )
11*c2c66affSColin Finck {
12*c2c66affSColin Finck 	close();
13*c2c66affSColin Finck 	_f = fopen ( filename, mode );
14*c2c66affSColin Finck 	return _f != 0;
15*c2c66affSColin Finck }
16*c2c66affSColin Finck 
getline(bool strip_crlf)17*c2c66affSColin Finck std::string File::getline ( bool strip_crlf /*= false*/ )
18*c2c66affSColin Finck {
19*c2c66affSColin Finck 	std::string s = "";
20*c2c66affSColin Finck 	char buf[256];
21*c2c66affSColin Finck 	for ( ;; )
22*c2c66affSColin Finck 	{
23*c2c66affSColin Finck 		*buf = 0;
24*c2c66affSColin Finck 		fgets ( buf, sizeof(buf)-1, _f );
25*c2c66affSColin Finck 		if ( !*buf )
26*c2c66affSColin Finck 			break;
27*c2c66affSColin Finck 		s += buf;
28*c2c66affSColin Finck 		if ( strchr ( "\r\n", buf[strlen(buf)-1] ) )
29*c2c66affSColin Finck 			break;
30*c2c66affSColin Finck 	}
31*c2c66affSColin Finck 	if ( strip_crlf )
32*c2c66affSColin Finck 	{
33*c2c66affSColin Finck 		char* p = strpbrk ( &s[0], "\r\n" );
34*c2c66affSColin Finck 		if ( p )
35*c2c66affSColin Finck 		{
36*c2c66affSColin Finck 			*p = '\0';
37*c2c66affSColin Finck 			s.resize ( p-&s[0] );
38*c2c66affSColin Finck 		}
39*c2c66affSColin Finck 	}
40*c2c66affSColin Finck 	return s;
41*c2c66affSColin Finck }
42*c2c66affSColin Finck 
43*c2c66affSColin Finck // this function searches for the next end-of-line and puts all data it
44*c2c66affSColin Finck // finds until then in the 'line' parameter.
45*c2c66affSColin Finck //
46*c2c66affSColin Finck // call continuously until the function returns false ( no more data )
next_line(std::string & line,bool strip_crlf)47*c2c66affSColin Finck bool File::next_line ( std::string& line, bool strip_crlf )
48*c2c66affSColin Finck {
49*c2c66affSColin Finck 	line = getline(strip_crlf);
50*c2c66affSColin Finck 	// indicate that we're done *if*:
51*c2c66affSColin Finck 	// 1) there's no more data, *and*
52*c2c66affSColin Finck 	// 2) we're at the end of the file
53*c2c66affSColin Finck 	return line.size()>0 || !eof();
54*c2c66affSColin Finck }
55*c2c66affSColin Finck 
56*c2c66affSColin Finck /*
57*c2c66affSColin Finck example usage:
58*c2c66affSColin Finck 
59*c2c66affSColin Finck bool mycallback ( const std::string& line, int line_number, long lparam )
60*c2c66affSColin Finck {
61*c2c66affSColin Finck 	std::cout << line << std::endl;
62*c2c66affSColin Finck 	return true; // continue enumeration
63*c2c66affSColin Finck }
64*c2c66affSColin Finck 
65*c2c66affSColin Finck File f ( "file.txt", "rb" ); // open file for binary read-only ( i.e. "rb" )
66*c2c66affSColin Finck f.enum_lines ( mycallback, 0, true );
67*c2c66affSColin Finck */
68*c2c66affSColin Finck 
enum_lines(bool (* callback)(const std::string & line,int line_number,long lparam),long lparam,bool strip_crlf)69*c2c66affSColin Finck bool File::enum_lines ( bool (*callback)(const std::string& line, int line_number, long lparam), long lparam, bool strip_crlf )
70*c2c66affSColin Finck {
71*c2c66affSColin Finck 	int line_number = 0;
72*c2c66affSColin Finck 	for ( ;; )
73*c2c66affSColin Finck 	{
74*c2c66affSColin Finck 		std::string s = getline(strip_crlf);
75*c2c66affSColin Finck 		line_number++;
76*c2c66affSColin Finck 		if ( !s.size() )
77*c2c66affSColin Finck 		{
78*c2c66affSColin Finck 			if ( eof() )
79*c2c66affSColin Finck 				return true;
80*c2c66affSColin Finck 			else
81*c2c66affSColin Finck 				continue;
82*c2c66affSColin Finck 		}
83*c2c66affSColin Finck 		if ( !(*callback) ( s, line_number, lparam ) )
84*c2c66affSColin Finck 			return false;
85*c2c66affSColin Finck 	}
86*c2c66affSColin Finck }
87*c2c66affSColin Finck 
length()88*c2c66affSColin Finck size_t File::length()
89*c2c66affSColin Finck {
90*c2c66affSColin Finck #ifdef WIN32
91*c2c66affSColin Finck 	return _filelength ( _fileno(_f) );
92*c2c66affSColin Finck #elif defined(UNIX)
93*c2c66affSColin Finck 	struct stat file_stat;
94*c2c66affSColin Finck 	verify(fstat(fileno(_f), &file_stat) == 0);
95*c2c66affSColin Finck 	return file_stat.st_size;
96*c2c66affSColin Finck #endif
97*c2c66affSColin Finck }
98*c2c66affSColin Finck 
close()99*c2c66affSColin Finck void File::close()
100*c2c66affSColin Finck {
101*c2c66affSColin Finck 	if ( _f )
102*c2c66affSColin Finck 	{
103*c2c66affSColin Finck 		fclose(_f);
104*c2c66affSColin Finck 		_f = 0;
105*c2c66affSColin Finck 	}
106*c2c66affSColin Finck }
107*c2c66affSColin Finck 
LoadIntoString(std::string & s,const char * filename)108*c2c66affSColin Finck /*static*/ bool File::LoadIntoString ( std::string& s, const char* filename )
109*c2c66affSColin Finck {
110*c2c66affSColin Finck 	File in ( filename, "rb" );
111*c2c66affSColin Finck 	if ( !in.isopened() )
112*c2c66affSColin Finck 		return false;
113*c2c66affSColin Finck 	size_t len = in.length();
114*c2c66affSColin Finck 	s.resize ( len + 1 );
115*c2c66affSColin Finck 	if ( !in.read ( &s[0], len ) )
116*c2c66affSColin Finck 		return false;
117*c2c66affSColin Finck 	s[len] = '\0';
118*c2c66affSColin Finck 	s.resize ( len );
119*c2c66affSColin Finck 	return true;
120*c2c66affSColin Finck }
121*c2c66affSColin Finck 
SaveFromString(const char * filename,const std::string & s,bool binary)122*c2c66affSColin Finck /*static*/ bool File::SaveFromString ( const char* filename, const std::string& s, bool binary )
123*c2c66affSColin Finck {
124*c2c66affSColin Finck 	File out ( filename, binary ? "wb" : "w" );
125*c2c66affSColin Finck 	if ( !out.isopened() )
126*c2c66affSColin Finck 		return false;
127*c2c66affSColin Finck 	out.write ( s.c_str(), s.size() );
128*c2c66affSColin Finck 	return true;
129*c2c66affSColin Finck }
130