The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
filesystem_sdl.cpp
Go to the documentation of this file.
1 #include <SDL.h>
2 #include <SDL_rwops.h>
3 
4 #include "filesystem.hpp"
5 #include "log.hpp"
6 
7 static lg::log_domain log_filesystem("filesystem");
8 #define ERR_FS LOG_STREAM(err, log_filesystem)
9 
10 namespace filesystem {
11 
12 static Sint64 ifs_size (struct SDL_RWops * context);
13 static Sint64 SDLCALL ifs_seek(struct SDL_RWops *context, Sint64 offset, int whence);
14 static size_t SDLCALL ifs_read(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum);
15 static size_t SDLCALL ifs_write(struct SDL_RWops *context, const void *ptr, size_t size, size_t num);
16 static int SDLCALL ifs_close(struct SDL_RWops *context);
17 
18 SDL_RWops* load_RWops(const std::string &path) {
19  SDL_RWops *rw = SDL_AllocRW();
20 
21  rw->size = &ifs_size;
22  rw->seek = &ifs_seek;
23  rw->read = &ifs_read;
24  rw->write = &ifs_write;
25  rw->close = &ifs_close;
26 
27  rw->type = 7; // Random number that is larger than 5
28 
29  std::istream *ifs = istream_file(path);
30  if(!ifs) {
31  ERR_FS << "load_RWops: istream_file returned NULL on " << path << '\n';
32  return NULL;
33  }
34 
35  rw->hidden.unknown.data1 = ifs;
36 
37  return rw;
38 }
39 
40 
41 static Sint64 ifs_size (struct SDL_RWops * context) {
42  std::istream *ifs = static_cast<std::istream*>(context->hidden.unknown.data1);
43  std::streampos orig = ifs->tellg();
44 
45  ifs->seekg(0, std::ios::end);
46 
47  std::streampos len = ifs->tellg();
48 
49  ifs->seekg(orig);
50 
51  return len;
52 
53 }
54 
55 static Sint64 SDLCALL ifs_seek(struct SDL_RWops *context, Sint64 offset, int whence) {
56 
57  std::ios_base::seekdir seekdir;
58  switch(whence){
59  case RW_SEEK_SET:
60  seekdir = std::ios_base::beg;
61  if(offset < 0)
62  offset = 0;
63  break;
64  case RW_SEEK_CUR:
65  seekdir = std::ios_base::cur;
66  break;
67  case RW_SEEK_END:
68  seekdir = std::ios_base::end;
69  if(offset > 0)
70  offset = 0;
71  break;
72  default:
73  assert(false);
74  throw "assertion ignored";
75  }
76  std::istream *ifs = static_cast<std::istream*>(context->hidden.unknown.data1);
77  const std::ios_base::iostate saved_state = ifs->rdstate();
78 
79  ifs->seekg(offset, seekdir);
80 
81  if(saved_state != ifs->rdstate() && offset < 0) {
82  ifs->clear(saved_state);
83  ifs->seekg(0, std::ios_base::beg);
84  }
85 
86  std::streamsize pos = ifs->tellg();
87  return static_cast<int>(pos);
88 }
89 
90 static size_t SDLCALL ifs_read(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum) {
91  std::istream *ifs = static_cast<std::istream*>(context->hidden.unknown.data1);
92 
93  // This seems overly simplistic, but it's the same as mem_read's implementation
94  ifs->read(static_cast<char*>(ptr), maxnum * size);
95  std::streamsize num = ifs->good() ? maxnum : ifs->gcount() / size;
96 
97  // EOF sticks unless we clear it. Bad is an actual I/O error
98  if(!ifs->bad())
99  ifs->clear();
100 
101  return static_cast<int>(num);
102 }
103 
104 static size_t SDLCALL ifs_write(struct SDL_RWops * /*context*/, const void * /*ptr*/, size_t /*size*/, size_t /*num*/) {
105  SDL_SetError("Writing not implemented");
106  return 0;
107 }
108 static int SDLCALL ifs_close(struct SDL_RWops *context) {
109  if (context) {
110  std::istream *ifs = static_cast<std::istream*>(context->hidden.unknown.data1);
111  delete ifs;
112  SDL_FreeRW(context);
113  }
114  return 0;
115 }
116 
117 }
static Sint64 SDLCALL ifs_seek(struct SDL_RWops *context, Sint64 offset, int whence)
static int SDLCALL ifs_close(struct SDL_RWops *context)
int pos
Definition: formula.cpp:800
GLintptr offset
Definition: glew.h:1650
GLsizei const char ** path
Definition: glew.h:4654
GLuint GLuint end
Definition: glew.h:1221
GLenum GLsizei len
Definition: glew.h:5662
std::istream * istream_file(const std::string &fname, bool treat_failure_as_error=true)
GLuint num
Definition: glew.h:2552
Declarations for File-IO.
static Sint64 ifs_size(struct SDL_RWops *context)
GLsizeiptr size
Definition: glew.h:1649
static size_t SDLCALL ifs_read(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
Standard logging facilities (interface).
SDL_RWops * load_RWops(const std::string &path)
#define ERR_FS
static size_t SDLCALL ifs_write(struct SDL_RWops *context, const void *ptr, size_t size, size_t num)
GLsizei const GLcharARB ** string
Definition: glew.h:4503
static lg::log_domain log_filesystem("filesystem")