Multimaps & File Reading

Hi all,

I've got a problem with reading my file data but before I explain it I'll give some background. I'm programming a 2D Platformer using the SDL library for rendering.

My problem is that when reading in the data from the file it ignores all the data and just skips to the end of the function, I've attempted to debug it and the load function is getting called, the file is in the right directory and is being opened.

Here is my code:

Level.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include "gameobject.h"
#include "miscobject.h"

struct LevelData
{
	// Multimap Prototype
	std::multimap<std::string, GameObject*> l_RenderMap;

	// Misc layer to store MiscObjects
	std::multimap<std::string, MiscObject*>	l_MiscMap;	/* Render Layer: misc */

	// Tile spacing
	int							l_TileSpace; /* Spacing between map objects */

	// Level name to load by
	std::string					l_Name;	/* Map name */
};

class Level
{
public:
	Level();
	~Level();

	LevelData	getLevelData()			{ return m_Data; }
	void		setFileName(std::string n)	{ m_Data.l_Name = n; }

	void		renderLevel(SDL_Surface* scr);

	bool		insertObject(std::string layer, GameObject* obj);

	void		writeString(std::ofstream& file, const std::string& str);
	std::string	readString(std::ifstream& file, std::string& str);

	bool		save(std::string filepath, std::string mapname);
	bool		save(std::string filepath, std::string mapname, LevelData* level);
	bool		load(std::string filepath, std::string mapname);
	bool		load(std::string filepath, std::string mapname, LevelData* level);

private:
	LevelData	m_Data;
};


Level.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
bool Level::load(std::string filepath, std::string mapname)
{
	std::cout << "load called.\n";
        
        std::string path;
        path.append(filepath);
        path.append(mapname);
        path.append(".level");

	std::ifstream load(path.c_str(), std::ios_base::binary);

	if(load.is_open())
	{
		GameObject* obj;

		std::pair<std::multimap<std::string, GameObject*>::iterator, std::multimap<std::string, GameObject*>::iterator> ii;
		std::multimap<std::string, GameObject*>::iterator it;
		ii = m_Data.l_RenderMap.equal_range("Layer0");
		for(it = ii.first; it != ii.second; ++it)
		{
			load.read((char*)obj, sizeof(GameObject));
			std::cout << "Inserting object\n";
			if(insertObject("Layer0", obj))
				std::cout << "Object " << obj << " inserted.\n";
		}

		ii = m_Data.l_RenderMap.equal_range("Layer1");
		for(it = ii.first; it != ii.second; ++it)
		{
			load.read((char*)obj, sizeof(GameObject));
			insertObject("Layer1", obj);
		}

		ii = m_Data.l_RenderMap.equal_range("Layer2");
		for(it = ii.first; it != ii.second; ++it)
		{
			load.read((char*)obj, sizeof(GameObject));
			insertObject("Layer2", obj);
		}

		ii = m_Data.l_RenderMap.equal_range("Layer3");
		for(it = ii.first; it != ii.second; ++it)
		{
			load.read((char*)obj, sizeof(GameObject));
			insertObject("Layer3", obj);
		}

		// Load misc layer
		std::pair<std::multimap<std::string, MiscObject*>::iterator, std::multimap<std::string, MiscObject*>::iterator> iimisc;
		std::multimap<std::string, MiscObject*>::iterator itmisc;
		iimisc = m_Data.l_MiscMap.equal_range("Map");
		for(itmisc = iimisc.first; itmisc != iimisc.second; ++itmisc)
		{
			MiscObject* mobj;
			load.read((char*)mobj, sizeof(MiscObject));
			m_Data.l_MiscMap.insert(std::pair<std::string, MiscObject*>("Map", mobj));
		}

		// Load tile spacing
		load.read((char*)&m_Data.l_TileSpace, sizeof(int));

		// Load files name
		//readString(load, m_Data.l_Name);

		load.close();
		std::cout << "loading successful\n";
		return true;
	}
	else
	{
		std::cout << "Unable to load level data\n";
		return false;
	}
}


I'm not sure if it's the way I'm using multimaps (I only just learned about them recently) or some other problem within the code.

Any help is appreciated

edit: I should have mentioned that I put a break point in the multimap loops where it writes and inserts the objects and it doesn't seem to be hitting the functions, this is why I think there's something wrong with the multimaps.
Last edited on
obj isn't pointing to anywhere so where is will write to you don't know.
load.read((char*)obj, sizeof(GameObject));
Well I want to read the data into a variable temporarily so I can move it back into the multimap, how do I do that?
I reworked my save class to have an enum for each layer replacing the string in the multimap, then when I add my GameObjects I write the size of the elements within the key and the layer name. Then in my load function I read back the size and layer, loading in my objects until all the elements have been readded to the multimap and when there are no more elements go to the next layer. This seems to be working for me now no problem :) I'll leave the code here, hopefully it will help anyone else who is having problems reading and writing with multimaps.

Level.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include "gameobject.h"
#include "miscobject.h"

enum LevelFlags
{
	LEVEL_LAYER_0 = 0, /* Layer 0 */
	LEVEL_LAYER_1 = 1, /* Layer 1 */
	LEVEL_LAYER_2 = 2, /* Layer 2 */
	LEVEL_LAYER_3 = 3, /* Layer 3 */
	LEVEL_LAYER_M = 4, /* Misc Layer */
	LEVEL_LAYER_E = 5  /* End Layer */
};

struct LevelData
{
	// Render Layer
	std::multimap<LevelFlags, GameObject*> m_RenderMap;

	// Misc layer
	std::multimap<LevelFlags, MiscObject*>	m_MiscMap;

	// Tile spacing
	int			m_TileSpace; /* Spacing between map objects */

	// Level name to load by
	std::string		m_Name;	/* Map name */
	int			m_NameLength;
};

class Level
{
public:
	Level();
	~Level();

	LevelData			getLevelData()			{ return m_Data; }
	void				setFileName(std::string n)	{ m_Data.m_Name = n; }

	void				renderLevel(SDL_Surface* scr);

	bool				insertObject(LevelFlags flags, GameObject* obj);
	bool				insertMObject(LevelFlags flags, MiscObject* obj);

	void				writeString(std::ofstream& file, const std::string& str);
	std::string			readString(std::ifstream& file, std::string& str);

	bool				save(std::string filepath, std::string mapname,LevelData* level = 0);
	bool				load(std::string filepath, std::string mapname, LevelData* level = 0);

private:
	LevelData         	m_Data;
};


Level.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
bool Level::save(std::string filepath, std::string mapname, LevelData* level)
{
	std::string path;

	if(m_Data.m_Name != "")
	{
		path = filepath;
		mapname = m_Data.m_Name;
		mapname.append(".sld");
		path.append(mapname);
	}
	else
	{
		path = filepath;
		mapname.append(".sld");
		path.append(mapname);
	}

	std::ofstream save(path.c_str(), std::ios_base::binary);

	if(save.is_open())
	{
		// Save Render Layer
		std::pair<std::multimap<LevelFlags, GameObject*>::iterator, std::multimap<LevelFlags, GameObject*>::iterator> ii;
		std::multimap<LevelFlags, GameObject*>::iterator it;

		ii = m_Data.m_RenderMap.equal_range(LEVEL_LAYER_0);
		int layer = LEVEL_LAYER_0;
		save.write((char*)&layer, sizeof(int));
		int layerSize = std::distance(ii.first, ii.second);
		save.write((char*)&layerSize, sizeof(int));
		for(it = ii.first; it != ii.second; ++it)//REsave it
		{
			it->second->serialize(save);
		}

		ii = m_Data.m_RenderMap.equal_range(LEVEL_LAYER_1);
		layer = LEVEL_LAYER_1;
		save.write((char*)&layer, sizeof(int));
		layerSize = std::distance(ii.first, ii.second);
		save.write((char*)&layerSize, sizeof(int));
		for(it = ii.first; it != ii.second; ++it)
		{
			it->second->serialize(save);
		}

		ii = m_Data.m_RenderMap.equal_range(LEVEL_LAYER_2);
		layer = LEVEL_LAYER_2;
		save.write((char*)&layer, sizeof(int));
		layerSize = std::distance(ii.first, ii.second);
		save.write((char*)&layerSize, sizeof(int));
		for(it = ii.first; it != ii.second; ++it)
		{
			it->second->serialize(save);
		}

		ii = m_Data.m_RenderMap.equal_range(LEVEL_LAYER_3);
		layer = LEVEL_LAYER_3;
		save.write((char*)&layer, sizeof(int));
		layerSize = std::distance(ii.first, ii.second);
		save.write((char*)&layerSize, sizeof(int));
		for(it = ii.first; it != ii.second; ++it)
		{
			it->second->serialize(save);
		}

		// Save Misc Layer
		std::pair<std::multimap<LevelFlags, MiscObject*>::iterator, std::multimap<LevelFlags, MiscObject*>::iterator> iimisc;
		std::multimap<LevelFlags, MiscObject*>::iterator itmisc;

		iimisc = m_Data.m_MiscMap.equal_range(LEVEL_LAYER_M);
		layer = LEVEL_LAYER_M;
		save.write((char*)&layer, sizeof(int));
		layerSize = std::distance(ii.first, ii.second);
		save.write((char*)&layerSize, sizeof(int));
		for(itmisc = iimisc.first; itmisc != iimisc.second; ++itmisc)
		{
			itmisc->second->serialize(save);
		}

		layer = LEVEL_LAYER_E;
		save.write((char*)&layer, sizeof(int));
		// Save tile spacing
		save.write((char*)&m_Data.m_TileSpace, sizeof(int));

		// Save files name
		//writeString(save, m_Data.m_Name);

		save.close();
		return true;
	}

	return false;
}

bool Level::load(std::string filepath, std::string mapname, LevelData* level)
{
	std::string path;
	std::cout << "load called.\n";

	if(m_Data.m_Name != "")
	{
		path = filepath;
		mapname = m_Data.m_Name;
		mapname.append(".sld");
		path.append(mapname);
	}
	else
	{
		path = filepath;
		mapname.append(".sld");
		path.append(mapname);
	}

	std::ifstream load(path.c_str(), std::ios_base::binary);

	if(load.is_open())
	{
		// Read Render Layer
		int currentLayer = 0;
		int currentLayerSize = 0;
		GameObject gameobj;

		while(currentLayer != LEVEL_LAYER_M)
		{
			load.read((char*)&currentLayer, sizeof(int));
			load.read((char*)&currentLayerSize, sizeof(int));

			if(currentLayerSize > 0)
			{
				for(unsigned i = 0; i < currentLayerSize; i++)
				{
					gameobj.unserialize(load);
					insertObject(static_cast<LevelFlags>(currentLayer), new GameObject(gameobj));
				}
			}
		}

		// Read misc layer
		MiscObject miscobj;

		while(currentLayer != LEVEL_LAYER_E)
		{
			load.read((char*)&currentLayer, sizeof(int));
			load.read((char*)&currentLayerSize, sizeof(int));

			if(currentLayerSize > 0)
			{
				for(unsigned i = 0; i < currentLayerSize; i++)
				{
					miscobj.unserialize(load);
					insertMObject(static_cast<LevelFlags>(currentLayer), &miscobj);
				}
			}
		}

		// Load tile spacing
		load.read((char*)&m_Data.m_TileSpace, sizeof(int));

		// Load files name
		//readString(load, m_Data.l_Name);

		load.close();
		std::cout << "loading successful\n";
		return true;
	}
	else
	{
		std::cout << "Unable to load level data\n";
		return false;
	}

	return false;
}
Topic archived. No new replies allowed.