![]() |
|
Reading a packfile |
TeamTerradactyl
Member #7,733
September 2006
![]() |
I When reading in from the packfile, I would simply use:
However, I want to change the name from a character to a std::string. If I try to use the same routine, I'll have problems, since the size of the name will be different for each name. Is there an alternate method I could use to read in an unknown-sized string variable with pack_fread? One thought I had considered was something similar to std::cin.get(char c). It would only grab a single letter at a time, until it hit a '\0'. Or, if I specify a string-type to pack_fread, will it be able to keep reading in data until it finds the '\0' itself? Unfortunately, pack_fread didn't seem to have any "Similar topics" on the page that I could check out... Thanks if anyone knows!
|
Jakub Wasilewski
Member #3,653
June 2003
![]() |
One option is to write/read the strings using the length-content string format, like: // write pack_iputw(str.size(), f); pack_fputs(str.c_str(), f); // read pack_igetw(stringLength, f); char *buffer = new char[stringLength+1]; pack_fread(buffer, stringLength, f); buffer[stringLength] = '\0'; string sth = buffer; Of course, you can also store them as zero-delimited, and use something like: // write pack_fputs(str.c_str(), f); pack_putc('\0'); // read char c; string buffer = ""; while (c = pack_getc(f)) buffer += c; There is no easy built-in way, just wrap one of the above in two functions and use everywhere you need to save/load strings. Also, to clear some stuff up, concerning the variable-sized string you mention. Actually, std::string is always the same size in memory, just like any other object in C++. The problem stems from the fact that a std::string internally stores a pointer to a character array, which makes no sense after writing it to a file and reading it back from it. --------------------------- |
TeamTerradactyl
Member #7,733
September 2006
![]() |
Jakub, does the packfile save the number of bytes of data we are passing into it when saving, then? That would tremendously simplify things for me! If so, I may just have skipped that part So I can write to the packfile, telling it the size of my next string of text. Then, when I read it again, I first pull out the size of the data, and then the actual data? /me slaps forehead Thanks!!
|
Jakub Wasilewski
Member #3,653
June 2003
![]() |
Quote: Jakub, does the packfile save the number of bytes of data we are passing into it when saving, then? That would tremendously simplify things for me! Unfortunately, all packfiles provide is raw input/output, and the fputs/fgets pair. Almost everything works like the functions from stdio, so just look those up if you need reference for pack_xxx. The differences are documented in the Allegro manual. Actually, there is one pitfall with my code snippets above. Allegro's pack_fputs always saves stuff as UTF-8, which could cause various annoying errors with the code above. If you stick to ASCII you'll be okay, but if you need Unicode or Extended ASCII characters then you'll have to take care of this problem. --------------------------- |
TeamTerradactyl
Member #7,733
September 2006
![]() |
I think I've got it now. Let me know if this looks correct:
If so, thanks for the push in the right direction, Jakub! EDIT: Changed the code a little (forgot to save the size to the packfile in the previous revision).
|
Jakub Wasilewski
Member #3,653
June 2003
![]() |
Quote: This part won't work. Those buffers I used up there were declared for a reason. You try to read literal characters as the std::string object, which is bound to screw things up badly. Std::strings are quite different from char arrays - you can't treat them as such, you have to use appropriate constructors or operators to set the string. When writing, you can use c_str() to get a C-like character array. However, this can't be used when reading, because the c_str() array is not modifiable. --------------------------- |
TeamTerradactyl
Member #7,733
September 2006
![]() |
I understand allegro is written in C, and not for C++. Does that mean that allegro will never be able to use std::strings instead of char arrays?
|
Steve Terry
Member #1,989
March 2002
![]() |
You can use C++ with allegro, there is nothing stopping you from doing that. You however need to be careful when using strings with allegro and know the limitations of going from a char array to a string and vice versa. ___________________________________ |
TeamTerradactyl
Member #7,733
September 2006
![]() |
What I meant, was that there's not much chance that pack_fread() will ever utilize the std::string, is there? Unless they wanted to rewrite allegro in C++ (or can C call the std template?)... It's too bad. It's about as annoying as std::iostream not being able to use strings either on "theStream.open(std::string myString)"
|
Audric
Member #907
January 2001
|
You can always write wrapper functions... |
TeamTerradactyl
Member #7,733
September 2006
![]() |
Okay, now my next question: I don't see a way to save a double/float to a packfile (I'm looking at PACKFILE to see what to do). I see the following, but nothing which clearly explains what I need to use here: pack_getc // Returns the next character from a stream. pack_putc // Puts a character in the stream. pack_igetw // Like pack_getc(), but using 16-bit Intel byte ordering words. pack_iputw // Like pack_putc(), but using 16-bit Intel byte ordering words. pack_igetl // Like pack_getc(), but using 32-bit Intel byte ordering words. pack_iputl // Like pack_putc(), but using 32-bit Intel byte ordering words. pack_mgetw // Like pack_getc(), but using 16-bit Motorola byte ordering words. pack_mputw // Like pack_putc(), but using 16-bit Motorola byte ordering words. pack_mgetl // Like pack_getc(), but using 32-bit Motorola byte ordering words. pack_mputl // Like pack_putc(), but using 32-bit Motorola byte ordering words. Would I want to use the 32-bit ones, since double/float may need that precision?
|
Onewing
Member #6,152
August 2005
![]() |
I use my own method that just came natural (and somewhat from working on sockets). I'm not claiming it to be the best, it's just easy for me. For each item stored in my packfile, I write two chars (that's two bytes) to the beginning. Bytes can store from 0-255. These two bytes represent the size of the following data in bytes. It kind of looks like this: Then you'd pack_fwrite as normal using the ctransfer. This way, you are storing the size specifically within the file. I wrote a program to convert text files into this format, so I just use notepad to fill in the data and then use the converter to have it stored in a packfile. It's just what I do. ------------ |
|