[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Sv: Sv: PenguinFile



(started as private mail between me (Bjarke - probably don't know me) and Christian Reiniger)

<< << What do you mean by ppfUnmount(everything), do you mean like an
ppfUnmountAll() API, or what? >> >>

<< No, just a ppfUmount () call for every thing that has been mounted before.
ppfUmount () is to ppfMount like fclose () is to fopen (). >>

ahh, ok, it was just that (everything) that threw me off track...

<< << << That means updating a pak will require roughly that code:
while (there_is_another_update)
{
ppfMount (TheUpdatePak, TheCommonMountpoint, ppfMF_override_files);
} >> >> >>

<< << I thought mounting was strictly a temporary memory thing (?). So what
happens here is that the update pak is mounted with the pak-overloading
feature on the HARDDISK, rather than just altering some memory
structures? It would seem to me that that practically IS an
ppfUpdate()... :) >> >>


[it is a strictly memory thing]

<< I guess I'll have to write a detailed description of this for the docs, but
that will take a bit (The last doc update was a real rewriting/adding
orgy and I need a little break now ;) >>

I don't mind writing docs... I'm sure how good an idea that is just now, as you *very* probably have a better understanding on how PenguinFile works... :)

<< << However, I think I have a good idea on how to write paks of format 0 (I
take it that is what we are talking about here: format 0). I'm going to
explain it in C++, but converting to C is merely a matter of having an
additional struct argument to the functions.

First, we need a PakImage or PakMemImage or some suchs class. This class
would then have these functions: (the failure and success returns values
is of course somewhat unimportant) >> >>

<< I think I will use derivatives of the existing classes for this -
ppf_PakFileDir / ppf_PakFileFile versions specialized for being written at
once. I think that's a relatively clean solution and it shouldn't be
difficult. I just have to decide on what's the "nicest" way to implement
it. Ad I have to overcome my laziness ;) >>

I think the functions MapDirToImage(), MapDirStructureToImage() and MapFileStructureToImage() (as described in my orevious Email (also on the mailing list) would make it somewhat easier to work with these classes. If you are not going to call the class something with the word "image" in it, you may want to call these functions something different if you plan on using them... :)

<< << << Not yet. The memory mapping stuff will be however.  >> >> >>

<< << Well, I implemented all the POSIX directory handling functions used by
PenguinFile, and it still doesn't compile. I've noticed that all over
the code, delete is rutinely called on const pointers. I don't know
about your compiler, but my compiler does not accept this. What about >> >>

<< Why not? There's nothing wrong with it. "const" just means "please don't
modify that thing" - it does *not* mean that the memory isn't dynamically
allocated. >>

const does not mean "please don't modify that thing", it means "DON'T MODIFY THAT THING!", and a const pointer means "DON'T MODIFY WHATEVER THAT THING IS POINTING TO!". If I pass something to a function and the pointer parameter is declared as const, I expect that it hasn't changed when the function returns. This is exactly what the compiler is expecting too. When you do something like this:

const char* pString;
strcpy(pString, pWhatever);
DoWhatever(pString)
delete pString

A compiler shouldn't compile the delete line here: it's not proper C++. This would be valid:

delete (char*) pString

Or, to be more C++like:

delete const_cast<char*>(pString);

However, this is a BAD hack. It can, in some rare situations be nessecary to cast away (literally speaking :) the constness of a variable, but it should be avoided whenever possible. It's far worse than using, say, goto, if it's not strictly nessecary.

In this example, the pString variable shouldn't have been declared const from the beginning:


char* pString;
strcpy(pString, pWhatever);
DoWhatever(pString)
delete pString

This is fine. The pString is altered in this code part, and therefore it isn't declared const. If DoWhatever() doesn't alter it's argument, then it can declare it's argument const, if it doesn't, it can declare it without the const. Now, the neat thing is, that if you didn't plan on the pString variable getting altered (ie, you declared it const), but the DoWhatever function intended to change it's argument (ie, the argument is not declared const), the compiler would tell you by issuing an error that it could not convert one type to another on that line (where the only difference between the types is that one is const, the other isn't, so it's obvious that it's constness that's the problem).

Correctly used constness is a very important part of C++, and it is a tremendous help to move bugs from runtime to compile time: you tell the compiler what you don't want it to alter, and if you then do it anyway by mistake or intent, it will tell you: "hey, you told me I wasn't supposed to do that, and now you ask me to do it anyway, there's something wrong here". Then you can decide on wheter it really shouldn't be const, or if it was a bug to try to alter it.

I have an example from your code where you do this const deletion:

---------------

 const char *RelPath = ppf_GenRelativePath (PakPath, Path);
 delete[] Path;
 if (RelPath == 0) return 0;

 ppf_Directory *RootDir = ppf_GlobalData.GetDirTree (ppfAM_pakfile);
 if (RootDir == 0)
 {
  delete[] RelPath;
  return 0;
 }

 ppf_Directory *TheDir = RootDir->SearchDir (RelPath);
 delete[] RelPath;

---------------

Yes, that a pointer is const doesn't mean that it can't be dynamicly allocated, however it does mean that whatever it points to shouldn't be altered. Deleting what it points to is a rather drastic alteration of what it points to, I'd say... If you plan to alter something, don't make it const. A compiler should throw an error at you for doing something like this, though...

If you wanted the pointer variable itself to be const, then you should have declared it char const* RelPath.

I'm somewhat surprised you don't know this. Actually, I'm EXTREMELY surprised. That along with the fact that your compiler obviously doesn't consider this an error indicates to me that there's something weird going on here I don't know about...

<< << including config.h (what does it do, anyway?) in PenguinFile.h rather
than in each file. It seems to me it's used all over (?). >> >>

<< config.h *is* only included in PenguinPlay.h
It is generated by autoconf and contains some #defines for system specific
things (e.g. it defines WORDS_BIGENDIAN if we are on a big endian machine
(like a PPC)). >>

Ahh, yes, sorry. I think the reason for my misconseption most've beent hat every file generated a "can't find config.h" fatal error, but then that's of course because all files include "penguinplay.h"... :)

btw, what is endianess? It isn't even a word in my neither my normal nor computer-specific dictionary (ok, perhaps the computer-specific one isn't really a dictionary, but anyhow).


<< << MS VC++ has an *EXCELLENT* text editor. I simply couldn't imagine one
better. It places 2 project files in you source dir, and a temporary >> >>

<< Well, I'm using a better one. Do a search for "FTE", there's also a Win32
version of it. You might have to do some minor adjustments to the config
files first, but once you have that it's just plain wonderful :) >>

Does it do things like track your current indentation and automaticly create it when you press enter? Does it do this with virtual spaces (or tabs) (ie, they go away if you don't use them) ? Does it also track all your code and gives you a sidebar where you can get information on all your classes and functions, and click on any functions, or method of a class, to jump to it's implementation? (if you click a class, it goes to it's definition, btw) (EXTREMELY nice feature).

it can also generate a view-file which gives a visual representation of your code. This is generated from your code AFTER it has been compiled, so even things like this will be in it:

#define FIRST_PART_OF_DECLARATION char* GetStr
#define IMPL { }

FIRST_PART_OF_DECLARATION () const
IMPL

If you are also using MFC, it helps you out by literally writing half your code for you.

I don't believe your editor is better, but perhaps it's equally good, I don't know. I'll check it out, though; Perhaps it'll surprise me :)

<< << There's context-sensitive help on any keyword or error message 1 click >> >>

<< Ok, that's a bonus of an IDE... But usually I only need the manpages or some html docs >>

Believe me, you use the documentation much more if it's so easily accessable.

Did I mention that clickling any error message instantly brings up the window that the code where the line that generated the error is in and scrolls to and highlights that specific line of code? What about the fact that you can have two seperate projects open at once, viewing them both at the same time (no seperation of any kind, except that they are in different directories, of course)? Handy when you need to check out some code and alter it while looking at the origional, as I'm doing when I'm trying to get PenguinFile to compile on WIN32 (I have two copies of the code, one I alter and one I don't, and I can then always check out how it was before I altered it with a few clicks).

btw, setting breakpoints is as simple as putting the cursor on a line and pressing F9. It works that way too even when debugging is going on. VC++ environment is also used for several other languages (including Java, though support for that has been discontinued), so you can use the same interface you'r used to.

Windows is not a very good platform, but there's nothing wrong with VC++, nor the interface of Windows. It's what directly beneath it that's just... can't find the words for it, but it's not good :)

<< << << We have a simpler procedural event system for the lower levels >> >> >>

<< << Any documentation for that? >> >>

<< Nope, not yet. You'll have to look at the sources (src/PenguinEvent) or ask Adrian. >>

Ahh, ok. I'll do that.

<< << to read the modification times for windows files, as those are encoded as the amount of 100 nanosecond intervals that has elapsed since january 1, 1601. >> >>

<< Ugh. Who designed THAT ??? >>

Yeah, that's exactly the thought I had when I found out about it :)

But then I thought about it, and it's not that stupid anyway. A) it's stored 64 bit, so it can handle the better precision (for those without 64bit integers, it's implemented as a two-32-bit-member-variables struct), and B) I have a suspicion that it makes it more effecient to calculate leap-years and leap-centuries. In fact, 1600 is a leap-century (every centuri year, there is a year, that even if it has 4 as a divisor, it isn't a leap-year, with the exception that every 4 centuries, it IS a leapyear, with the exception that every 1000 years (or is it 2000?), it ISN'T a leapyear :), so that's probably why it's 1601. Considering the quite complicated task of getting the leap-thingies (insert year, centuri or millenia) right, I guess any help is welcomed by the people who have to implement it... It does make the job of creating platform-independant libs a little harder, but then, converting isn't THAT hard: the only catch is to calculate all the leap-thingies from january 1, 1601 to januart 1, 1930.


<< << btw, why are you testing the return value of strcpy() to make sure that it is the same as the destination string? It would seem to me that that there is no case in which these would not be the same... >> >>

<< Except when strcpy() fails. In such a case it returns something else. It's unlikely, ok, but return values *should* be checked. >>

Let me give you a quite from my documentation: [on strcpy(), wspcpy() and _mbscpy()]

"Each of these functions returns the destination string. No return value is reserved to indicate an error."

and further down, it goes on:

"No overflow checking is performed when strings are copied or appended. The behavior of strcpy is undefined if the source and destination strings overlap."

And that's all that it mentions about error conditions. It mentions nothing about the return value being different form the destination, and it quite specificly say that there is no error checking and no error return. The example given of the functionality of strcpy() also does not include any return-value checking. Is your documentation different from mine?

PS. I got Linux installed yesterday :)  It was quite a grueling thing to do though: I deleted a partition of my harddisk I never used anyway (the computer came that way), but then the computer completely locked (wouldn't even boot, and bootdisks didn't work, for some weird reason), and then I thought that maybe my harddisk was compressed and I had just deleted the uncompressed partition that contained the information on how to decompress the compressed drive, thereby effectively deleting ALL my data (!!!). I thought that for quite some time, actually :)  Then I thought "ahh well, I can just as well install linux anyway", and I then went on to do that, but there apparently was something wrong with the harddrive, because the partitions made my diskdruid just didn't work and made red hat complain and I got nowhere. Then I tried taking the CD out, and what d' ya' know, the thing suddenly booted into Windows and all my data was there! Phew! Then I proceeded and tried install linux again, this time without any problems. Well, almost, at the time, it's complaining (linux) at start-up that it can't mount the swap drive for some reason. That actually crashed it, so I had to delete the linux partitions and install linux again. It's working now, but it still can't mount the swapdrive... btw, how do you get to the consol from Gnome? Right now I just start in the consol and restart when I want to go there... 

<< Christian >>

<< PS: What about moving this discussion to the mailing list? >>

Hereby done :)


I didn't forward your Email to the list, as that would be quite rude... If it's no problem, it could be a good idea, though.