NextPackEntry() return value question

Everything else that doesn't fall into one of the other PB categories.
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

NextPackEntry() return value question

Post by Kukulkan »

Hi. I face issues with Packer library and during some investigation I found some confusing behaviour.

The documentation for NextPackEntry() says:

Return value: Nonzero if the pack contain another entry, zero otherwise.

This also makes sense. This is how such works. So it returns 0 if no further entry exists.

But this code proofs that wrong:

Code: Select all

UseZipPacker()

infile.s = GetTemporaryDirectory()+"testfile.txt"
outfile.s = GetTemporaryDirectory()+"testfile.zip"

If OpenFile(0, infile.s)
  WriteStringN(0, "Some test content for ZIP archive test")
  CloseFile(0)
EndIf

; create a zip file
hZip = CreatePack(#PB_Any, outfile)
ret = AddPackFile(hZip, infile, GetFilePart(infile))
ClosePack(hZip)

; open the zip file
hZip = OpenPack(#PB_Any, outfile) 
If ExaminePack(hZip)
  Repeat 
    ret = NextPackEntry(hZip) ; DOCS: Returns nonzero if the pack contains another entry, zero otherwise. 
    Debug "Ret: " + str(ret) + " Name: " + PackEntryName(hZip) + ", Size: " + PackEntrySize(hZip)
  Until ret = 0
EndIf
ClosePack(hZip)

DeleteFile(infile.s)
DeleteFile(outfile.s)
Output:

Code: Select all

Ret: 1 Name: testfile.txt, Size: 40
Ret: 0 Name: , Size: 0
As you can see, NextPackEntry() returns 1 even if there is no further entry. Because of this, the second entry is output here.

I tested this on Windows 10 with PB 5.71, PB 5.73 and PB 6.00 beta6. All are affected the same way.

Is this really a bug or did I missunderstood something here?
User avatar
jacdelad
Addict
Addict
Posts: 1431
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: NextPackEntry() return value question

Post by jacdelad »

I'm not good at explaining, but: your loop is doing exactly what it is meant to do.
NextPackEntry delivers <>0 if the next data for the next entry could be loaded. So it is 1 the first time it is called, because an entry was found. At the end of the loop the return value is still 1 -> goto start of loop. Catch next entry -> there is none, but the loop is still executed until it reaches its end.

The "right" way:

Code: Select all

UseZipPacker()

infile.s = GetTemporaryDirectory()+"testfile.txt"
outfile.s = GetTemporaryDirectory()+"testfile.zip"

If OpenFile(0, infile.s)
  WriteStringN(0, "Some test content for ZIP archive test")
  CloseFile(0)
EndIf

; create a zip file
hZip = CreatePack(#PB_Any, outfile)
RET = AddPackFile(hZip, infile, GetFilePart(infile))
ClosePack(hZip)

; open the zip file
hZip = OpenPack(#PB_Any, outfile) 
If ExaminePack(hZip)
  While NextPackEntry(hZip)
    Debug "Name: " + PackEntryName(hZip) + ", Size: " + PackEntrySize(hZip)
  Wend
EndIf
ClosePack(hZip)

DeleteFile(infile.s)
DeleteFile(outfile.s)
Also working, but in the way you wanted to build it (add an "If"):

Code: Select all

UseZipPacker()

infile.s = GetTemporaryDirectory()+"testfile.txt"
outfile.s = GetTemporaryDirectory()+"testfile.zip"

If OpenFile(0, infile.s)
  WriteStringN(0, "Some test content for ZIP archive test")
  CloseFile(0)
EndIf

; create a zip file
hZip = CreatePack(#PB_Any, outfile)
RET = AddPackFile(hZip, infile, GetFilePart(infile))
ClosePack(hZip)

; open the zip file
hZip = OpenPack(#PB_Any, outfile) 
If ExaminePack(hZip)
  Repeat 
    RET = NextPackEntry(hZip) ; DOCS: Returns nonzero if the pack contains another entry, zero otherwise. 
    If RET
      Debug "Ret: " + Str(RET) + " Name: " + PackEntryName(hZip) + ", Size: " + PackEntrySize(hZip)
    EndIf
  Until RET = 0
EndIf
ClosePack(hZip)

DeleteFile(infile.s)
DeleteFile(outfile.s)
It's the same way that ExamineDirectory and other Examine-commands work.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: NextPackEntry() return value question

Post by Kukulkan »

Thanks, but you saying

NextPackEntry delivers <>0 if the next data for the next entry could be loaded.

But there is no next entry. Just this one (first).

And the docs are saying:

Nonzero if the pack contain another entry, zero otherwise.

I read it like "if there is 0, this is the last entry. Otherwise, there are others.". So the return value <> 0 indicates that there is another entry than the current one, which is simply wrong.

The thing is that I have such code:

Code: Select all

If ExaminePack(hZip)
  If NextPackEntry(hZip)
    Debug "Name: " + PackEntryName(hZip) + ", Size: " + PackEntrySize(hZip)
  EndIf
EndIf
This worked for many years now. But if the creator of the message was compiled with PB 5.73, it fails for these files as NextPackEntry() now returns 0 (like in the docs) and the first entry is not read. This is how I found that.
User avatar
jacdelad
Addict
Addict
Posts: 1431
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: NextPackEntry() return value question

Post by jacdelad »

The first time, after the Repeat, the first entry is loaed by calling NextPackEntry. Now you can use PackEntryName, PackEntrySize etc. on it.
Then you reach the bottom of your Repeat-loop. RET is still 1, the loop is called once more.
The next time it's called, it delivers 0, because there are no more entries. PackEntryXXX delivers garbage, because no entry is loaded.
-> The loop is executed twice, but just one entry is in the zip. If you have a zip with 100 entries, the loop will be called 101 times. Etc.

The code above works, because NextPack Entry is called once, so the first item is loaded and can be processed.

The ANOTHER entry means another entry was loaded. Not that there are more to be loaded later.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: NextPackEntry() return value question

Post by Kukulkan »

I understand what you say and I appreciate your answers and help. This is how it obviously works.

You say, a return value <> 0 means that a valid entry was selected (now available). And the reality seems to proof you.

But my point is, the docs saying something else...

Nonzero if the pack contain another entry, zero otherwise.

But there isn't another entry. Just the current one.
User avatar
jacdelad
Addict
Addict
Posts: 1431
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: NextPackEntry() return value question

Post by jacdelad »

The "another entry" is becoming the current at the moment you call NextPackEntry. It's the same way NextElement works for linked lists.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
User avatar
mk-soft
Always Here
Always Here
Posts: 5333
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: NextPackEntry() return value question

Post by mk-soft »

;)

Code: Select all

While NextPackEntry(hZip)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 16616
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: NextPackEntry() return value question

Post by Fred »

May be the wording is not correct, but it works like all other NextXXX() commands, nonzero if there is something found, or zero if it's the end of the listing. If you have another sentence to explain it better, I will amend the doc.
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: NextPackEntry() return value question

Post by Kukulkan »

Hi Fred,

better to say

Returns <> 0 if there is a valid entry available. Returns 0 if you reached the end (do not call PackEntryName(), PackEntrySize(), PackEntryType() any more).
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: NextPackEntry() return value question

Post by Little John »

A short example code tells more than 1000 words. :D

Obviously, the key is here to use a proper While loop.
Post Reply