1 /**
2  * Copyright (c) 2006-2016 LOVE Development Team
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty.  In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  *    claim that you wrote the original software. If you use this software
14  *    in a product, an acknowledgment in the product documentation would be
15  *    appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  *    misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  **/
20 
21 #include "File.h"
22 
23 namespace love
24 {
25 namespace filesystem
26 {
27 
~File()28 File::~File()
29 {
30 }
31 
read(int64 size)32 FileData *File::read(int64 size)
33 {
34 	bool isopen = isOpen();
35 
36 	if (!isopen && !open(MODE_READ))
37 		throw love::Exception("Could not read file %s.", getFilename().c_str());
38 
39 	int64 max = getSize();
40 	int64 cur = tell();
41 	size = (size == ALL) ? max : size;
42 
43 	if (size < 0)
44 		throw love::Exception("Invalid read size.");
45 
46 	// Clamping because the file offset may be in a weird position.
47 	if (cur < 0)
48 		cur = 0;
49 	else if (cur > max)
50 		cur = max;
51 
52 	if (cur + size > max)
53 		size = max - cur;
54 
55 	FileData *fileData = new FileData(size, getFilename());
56 	int64 bytesRead = read(fileData->getData(), size);
57 
58 	if (bytesRead < 0 || (bytesRead == 0 && bytesRead != size))
59 	{
60 		delete fileData;
61 		throw love::Exception("Could not read from file.");
62 	}
63 
64 	if (bytesRead < size)
65 	{
66 		FileData *tmpFileData = new FileData(bytesRead, getFilename());
67 		memcpy(tmpFileData->getData(), fileData->getData(), (size_t) bytesRead);
68 		fileData->release();
69 		fileData = tmpFileData;
70 	}
71 
72 	if (!isopen)
73 		close();
74 
75 	return fileData;
76 }
77 
write(const Data * data,int64 size)78 bool File::write(const Data *data, int64 size)
79 {
80 	return write(data->getData(), (size == ALL) ? data->getSize() : size);
81 }
82 
getExtension() const83 std::string File::getExtension() const
84 {
85 	const std::string &filename = getFilename();
86 	std::string::size_type idx = filename.rfind('.');
87 
88 	if (idx != std::string::npos)
89 		return filename.substr(idx+1);
90 	else
91 		return std::string();
92 }
93 
getConstant(const char * in,Mode & out)94 bool File::getConstant(const char *in, Mode &out)
95 {
96 	return modes.find(in, out);
97 }
98 
getConstant(Mode in,const char * & out)99 bool File::getConstant(Mode in, const char *&out)
100 {
101 	return modes.find(in, out);
102 }
103 
getConstant(const char * in,BufferMode & out)104 bool File::getConstant(const char *in, BufferMode &out)
105 {
106 	return bufferModes.find(in, out);
107 }
108 
getConstant(BufferMode in,const char * & out)109 bool File::getConstant(BufferMode in, const char *&out)
110 {
111 	return bufferModes.find(in, out);
112 }
113 
114 StringMap<File::Mode, File::MODE_MAX_ENUM>::Entry File::modeEntries[] =
115 {
116 	{"c", File::MODE_CLOSED},
117 	{"r", File::MODE_READ},
118 	{"w", File::MODE_WRITE},
119 	{"a", File::MODE_APPEND},
120 };
121 
122 StringMap<File::Mode, File::MODE_MAX_ENUM> File::modes(File::modeEntries, sizeof(File::modeEntries));
123 
124 StringMap<File::BufferMode, File::BUFFER_MAX_ENUM>::Entry File::bufferModeEntries[] =
125 {
126 	{"none", File::BUFFER_NONE},
127 	{"line", File::BUFFER_LINE},
128 	{"full", File::BUFFER_FULL},
129 };
130 
131 StringMap<File::BufferMode, File::BUFFER_MAX_ENUM> File::bufferModes(File::bufferModeEntries, sizeof(File::bufferModeEntries));
132 
133 } // filesystem
134 } // love
135