[#11822] RCR: Input XML support in the base Ruby — Dave Thomas <Dave@...>

15 messages 2001/03/01

[#11960] Not Ruby, for me, for the moment at least — "Michael Kreuzer" <mkreuzer@... (nospam)>

I wrote on this newsgroup last weekend about how I was considering using

11 messages 2001/03/04

[#12023] French RUG ? — "Jerome" <jeromg@...>

Hi fellow rubyers,

16 messages 2001/03/05

[#12103] disassembling and reassembling a hash — raja@... (Raja S.)

Given a hash, h1, will the following always hold?

20 messages 2001/03/06

[#12204] FEATURE REQUEST: 'my' local variables — Leo Razoumov <see_signature@127.0.0.1>

Ruby is, indeed, a very well designed language.

64 messages 2001/03/07
[#12250] Re: FEATURE REQUEST: 'my' local variables — Leo Razoumov <see_signature@127.0.0.1> 2001/03/07

>>>>> "GK" == GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp> writes:

[#12284] Re: FEATURE REQUEST: 'my' local variables — gotoken@... (GOTO Kentaro) 2001/03/08

In message "[ruby-talk:12250] Re: FEATURE REQUEST: 'my' local variables"

[#12289] Re: FEATURE REQUEST: 'my' local variables — matz@... (Yukihiro Matsumoto) 2001/03/08

Hi,

[#12452] Re: FEATURE REQUEST: 'my' local variables — gotoken@... (GOTO Kentaro) 2001/03/12

In message "[ruby-talk:12289] Re: FEATURE REQUEST: 'my' local variables"

[#12553] Re: FEATURE REQUEST: 'my' local variables — Dave Thomas <Dave@...> 2001/03/13

matz@zetabits.com (Yukihiro Matsumoto) writes:

[#12329] Math package — Mathieu Bouchard <matju@...>

18 messages 2001/03/09

[#12330] Haskell goodies, RCR and challenge — Robert Feldt <feldt@...>

Hi,

19 messages 2001/03/09
[#12374] Re: Haskell goodies, RCR and challenge — matz@... (Yukihiro Matsumoto) 2001/03/10

Hi,

[#12349] Can Ruby-GTK display Gif Png or Jpeg files? — Phlip <phlip_cpp@...>

Ruby-san:

20 messages 2001/03/09

[#12444] class variables — Max Ischenko <max@...>

14 messages 2001/03/12

[#12606] Order, chaos, and change requests :) — Dave Thomas <Dave@...>

17 messages 2001/03/14

[#12635] email address regexp — "David Fung" <dfung@...>

i would like to locate probable email addresses in a bunch of text files,

12 messages 2001/03/14

[#12646] police warns you -- Perl is dangerous!! — Leo Razoumov <see_signature@127.0.0.1>

I just read this story on Slashdot

14 messages 2001/03/14
[#12651] Re: police warns you -- Perl is dangerous!! — pete@... (Pete Kernan) 2001/03/14

On 14 Mar 2001 11:46:35 -0800, Leo Razoumov <see_signature@127.0.0.1> wrote:

[#12691] Re: police warns you -- Perl is dangerous!! — "W. Kent Starr" <elderburn@...> 2001/03/15

On Wednesday 14 March 2001 15:40, Pete Kernan wrote:

[#12709] [OFFTOPIC] Re: police warns you -- Perl is dangerous!! — Stephen White <spwhite@...> 2001/03/16

On Fri, 16 Mar 2001, W. Kent Starr wrote:

[#12655] Re: FEATURE REQUEST: 'my' local variables — "Benjamin J. Tilly" <ben_tilly@...>

>===== Original Message From Leo Razoumov <see_signature@127.0.0.1> =====

18 messages 2001/03/14

[#12706] Library packaging — "Nathaniel Talbott" <ntalbott@...>

I have a project that I'm working on that needs to live two different lives,

30 messages 2001/03/16

[#12840] Looking for a decent compression scheme — Dave Thomas <Dave@...>

14 messages 2001/03/19

[#12895] differences between range and array — "Doug Edmunds" <dae_alt3@...>

This code comes from the online code examples for

16 messages 2001/03/20
[#12896] Re: differences between range and array — "Hee-Sob Park" <phasis@...> 2001/03/20

[#12899] Re: differences between range and array — Jim Freeze <jim@...> 2001/03/20

On Tue, 20 Mar 2001, Hee-Sob Park wrote:

[#12960] TextBox ListBox — Ron Jeffries <ronjeffries@...>

Attached is a little Spike that Chet and I are doing. It is a

13 messages 2001/03/20

[#12991] [ANN] Lapidary 0.2.0 — "Nathaniel Talbott" <ntalbott@...>

Well, here's my first major contribution to the Ruby world: Lapidary. It's a

16 messages 2001/03/20

[#13028] mkmf question — Luigi Ballabio <luigi.ballabio@...>

15 messages 2001/03/21

[#13185] Reading a file backwards — "Daniel Berger" <djberg96@...>

Hi all,

21 messages 2001/03/25
[#13197] Re: Reading a file backwards — "Daniel Berger" <djberg96@...> 2001/03/25

> Hi Dan,

[#13203] Re: Reading a file backwards — Mathieu Bouchard <matju@...> 2001/03/25

On Sun, 25 Mar 2001, Daniel Berger wrote:

[#13210] Re: Reading a file backwards — "Daniel Berger" <djberg96@...> 2001/03/25

"Mathieu Bouchard" <matju@sympatico.ca> wrote in message

[#13374] Passing an array to `exec'? — Lloyd Zusman <ljz@...>

I'd like to do the following:

15 messages 2001/03/31

[#13397] Multidimensional arrays and hashes? — Lloyd Zusman <ljz@...>

Is it possible in ruby to make use of constructs that correspond to

14 messages 2001/03/31

[ruby-talk:12587] Re: Strange segmentation fault problem with C++ extension [source] LONG

From: "Paul C" <paul_c@...>
Date: 2001-03-13 22:10:06 UTC
List: ruby-talk #12587
"ts" <decoux@moulon.inra.fr> wrote in message
news:200103130555.f2D5tsr17121@orsay1.moulon.inra.fr...
> >>>>> "P" == Paul C <paul_c@passtheaardvark.com> writes:
>
> P>             zipLocalEntry = ZipLocalEntry_new ( ptr_entry ) ;
>
>  What is missing is the source of ZipLocalEntry_new, to see how you create
>  your object.
>
>
> Guy Decoux

For some reason my news account doesnt seem to like me posting attachments
(or at least they dont show up at my end) and I have therefore attached the
source code for the offending module below. If anyone would like me to email
as an attachment pse let me know.

Apologies to anyone who ends up getting this multiple times

========= Original Message =========

Guy,

I am attaching the source code for the module. To compile it you need to
install the zipios++ (zipios.sourceforge.com) and run extconf.rb
with --zipios-(include|lib) set appropriately (extconf.rb is a bit of a hack
in order to detect the c++ libs properly).

I have added some instrumentation to the ZipLocalEntry_new - the debug trace
with this added is below.

Thanks, Paul

=========== DEBUG TRACE ===========

# irb --prompt xmp

require 'Zip'
    ==>true

z = Zip::ZipFile.new "test.zip"
    ==>#<Zip::ZipFile:0x816c4ec @name="test.zip">

z.entries { |e| print e.path, "\n" }   # Get Zip Directory
    (zip.cpp:279) MSG: Entering Function #ZipLocalEntry_new
    (zip.cpp:280) PTR: ConstEntryPointer ->135928464
    (zip.cpp:284) PTR: zipLocalEntry ->135469952
    (zip.cpp:289) VALUE: rbZipLocalEntry -> #<Zip::ZipEntry:0x815f738
@path="extconf.rb">
    (zip.cpp:290) MSG: Leaving Function #ZipLocalEntry_new
extconf.rb
    (zip.cpp:279) MSG: Entering Function #ZipLocalEntry_new
    (zip.cpp:280) PTR: ConstEntryPointer ->135928468
    (zip.cpp:284) PTR: zipLocalEntry ->135470080
    (zip.cpp:289) VALUE: rbZipLocalEntry -> #<Zip::ZipEntry:0x815f558
@path="Makefile">
    (zip.cpp:290) MSG: Leaving Function #ZipLocalEntry_new
Makefile
    ==>#<Zip::ZipFile:0x816c4ec @name="test.zip">

z.entry "extconf.rb"                   # OK
    (zip.cpp:403) MSG: Entering Function #ZipFile_entry
    (zip.cpp:404) VALUE: self -> #<Zip::ZipFile:0x816c4ec @name="test.zip">
    (zip.cpp:408) PTR: ZipFile ->135501760
    (zip.cpp:418) MSG: GetEntry OK
    (zip.cpp:420) PTR: ConstEntryPointer ->135871104
    (zip.cpp:279) MSG: Entering Function #ZipLocalEntry_new
    (zip.cpp:280) PTR: ConstEntryPointer ->135871104
    (zip.cpp:284) PTR: zipLocalEntry ->135489024
    (zip.cpp:289) VALUE: rbZipLocalEntry -> #<Zip::ZipEntry:0x81545cc
@path="extconf.rb">
    (zip.cpp:290) MSG: Leaving Function #ZipLocalEntry_new
    (zip.cpp:422) VALUE: zipLocalEntry -> #<Zip::ZipEntry:0x81545cc
@path="extconf.rb">
    (zip.cpp:423) MSG: Leaving Function #ZipFile_entry
    ==>#<Zip::ZipEntry:0x81545cc @path="extconf.rb">

z.entry "zzzzzzz"                      # Invalid Entry
    (zip.cpp:403) MSG: Entering Function #ZipFile_entry
    (zip.cpp:404) VALUE: self -> #<Zip::ZipFile:0x816c4ec @name="test.zip">
    (zip.cpp:408) PTR: ZipFile ->135501760
    (zip.cpp:413) MSG: GetEntry Failed
RuntimeError: Entry not found
(irb):10:in `entry'
(irb):10:in `irb_binding'

z.entry "extconf.rb"                   # Should be OK
    (zip.cpp:403) MSG: Entering Function #ZipFile_entry
    (zip.cpp:404) VALUE: self -> #<Zip::ZipFile:0x816c4ec @name="test.zip">
    (zip.cpp:408) PTR: ZipFile ->135501760
    (zip.cpp:418) MSG: GetEntry OK
    (zip.cpp:420) PTR: ConstEntryPointer ->136008400
    (zip.cpp:279) MSG: Entering Function #ZipLocalEntry_new
    (zip.cpp:280) PTR: ConstEntryPointer ->136008400
    (zip.cpp:284) PTR: zipLocalEntry ->135126848
    (zip.cpp:289) VALUE: rbZipLocalEntry -> #<Zip::ZipEntry:0x814d2f4
@path="extconf.rb">
    (zip.cpp:290) MSG: Leaving Function #ZipLocalEntry_new
    (zip.cpp:422) VALUE: zipLocalEntry -> #<Zip::ZipEntry:0x814d2f4
@path="extconf.rb">
    (zip.cpp:423) MSG: Leaving Function #ZipFile_entry
(irb):12: [BUG] Segmentation fault
ruby 1.6.3 (2001-03-07) [i386-netbsd1.5]
Abort (core dumped)



====== extconf.rb =====
require 'mkmf'

CPP.gsub! /g?cc/, "c++"
LINK.gsub! /g?cc/, "c++"

dir_config ( "zipios" ) ;

if ( have_header ( "zipios++/zipfile.h" ) and
     have_library ( "gcc", "__pure_virtual" ) and
     have_library ( "zipios", "FListScannerwrap" ) and
     have_library ( "z", "inflate" ) and
     have_library ( "stdc++", "cin" ) )

    $defs[-1].tr! ( "++", "" )

    create_makefile ( "Zip" )
end

====== zip.cpp =====
//
// zip.cpp
//
// Ruby extension to use the Zipios++ Zip file reader library
// (http://zipios.sourceforge.com)
//
// Module
//
//      Zip - Module Namespace
//
// Classes
//
//      Zip::ZipFile - Zip File
//      Zip::ZipEntry - Zip File Entry
//
// Methods
//
// Zip::ZipFile
// ============
//
//      Zip::ZipFile#new (fileName, [fileOffset=0]) -> ZipFile
//
//          Constructor - open zip file
//
//      Zip::ZipFile#openEmbeddedZipFile (fileName) -> ZipFile
//
//          Constructor - open zIp file appended to another file
//
//          File must have Zip file offset encoded in last 4 bytes
//          in Zip file (little endian byte order) eg. using
//          'appendzip' program from zipios++ distribution
//
//      ZipFile#inspect -> String
//
//      ZipFile#name -> String
//
//          Return Zip file name
//
//      ZipFile#items -> Number
//
//          Returns number of items in ZipFile
//
//      ZipFile#entry -> ZipEntry List
//
//          Return ZipEntry list (contents) for ZipFile
//          In block context call block once for each entry
//
//      ZipFile#entries ( pathString ) -> ZipEntry
//
//          Return ZipEntry for given path
//          Raises RuntimeError is entry not found
//
//      ZipFile#getData ( ZipEntry | pathString ) -> String
//
//          Returns uncompressed data for ZipEntry or pathString
//          Raises RuntimeError is entry not found
//
// Zip::ZipEntry
// =============
//
// Note: There is no direct sconstructor for Zip::ZipEntry - must
// created through ZipFile#entry or ZipFile#entries
//
//      ZipEntry#inspect -> String
//
//      (The following ZipEntry methods are largely accessors for the
//      ZipEntry file attributes)
//
//      ZipEntry#comment -> String
//      ZipEntry#compressed_size -> Number
//      ZipEntry#crc -> Number (this doesnt look right??)
//      ZipEntry#size -> Number
//      ZipEntry#time -> Number (format not defined - see Zipios docs)
//      ZipEntry#isValid? -> Boolean
//      ZipEntry#isDirectory? -> Boolean
//      ZipEntry#path
//      ZipEntry#filename
//
// BUGS/TODO
//
//      - Fix ZipEntry#entry coredump
//      - Utility to create embedded Zipfiles
//      - Convert ZipEntry#time to Ruby date
//      - ZipStream support (code removed until I work out how to fix)
//      - Use Ruby IO object in ZipFile#new (may need complete rewrite)
//
//      On reflection it might have been easier to write simple C
//      extension supporting the Zip file structure and reuse the Ruby
//      Zlib module for decompression
//
// LICENSE
//
//      The zipios++ library is released under the GNU LGPL
//      (http://www.gnu.org/copyleft/lesser.html)
//
//      Ruby is releaed under a combined GPL/Artistic lisence
//      (http://www.ruby-lang.org/en/LICENSE.txt)
//
//      This code is freely distributable under whatever the combined
//      restrictions of the two above licenses might be
//
// Author: Paul Charvavarti (paul_c@passtheaardvark.com)
//
// $Id: zip.cpp,v 1.1.1.1 2001/03/13 17:43:52 paulc Exp $
//
// $Log: zip.cpp,v $
// Revision 1.1.1.1  2001/03/13 17:43:52  paulc
// Initial Import
//
//


extern "C" {
#include "ruby.h"
}

#include "zipios++/zipfile.h"
#include "zipios++/zipinputstream.h"
#include "zipios++/ziphead.h"

//
// C++ object wrapper macros stolen from SWIG
//

#define VALUEFUNC(f) ((VALUE (*)(...))f)
#define VOIDFUNC(f) ((void (*)(...))f)

#define Wrap_Class(klass,mark,free,ptr) \
    ((ptr)?Data_Wrap_Struct(klass,VOIDFUNC(mark),VOIDFUNC(free),ptr):Qnil)

#define Get_Class(val,rtype,ctype,ptr) {\
    if (NIL_P(val)) ptr = NULL;\
    else {\
        if (!rb_obj_is_kind_of(val, rtype))\
            rb_raise(rb_eTypeError, "Wrong argument type");\
        Data_Get_Struct(val, ctype, ptr);\
        if (!ptr) rb_raise(rb_eRuntimeError, "Class already released");\
    }\
}

#define Wrap_ZipFile(klass,ptr) \
    Wrap_Class(klass,0,free_ZipFile,ptr)
#define Get_ZipFile(val,ptr) \
    Get_Class(val,cZipFile,ZipFile,ptr)
#define Wrap_ZipLocalEntry(klass,ptr) \
    Wrap_Class(klass,0,free_ZipLocalEntry,ptr)
#define Get_ZipLocalEntry(val,ptr) \
    Get_Class(val,cZipLocalEntry,ZipLocalEntry,ptr)

//
// Debug macros - compile with -DDEBUG to enable
//

#define VALUE2STR(value) STR2CSTR(rb_funcall(value,rb_intern("to_s"),0))

#ifdef DEBUG
#define DEBUG_MSG(msg) printf ( "    (%s:%d) MSG: %s\n", \
                __FILE__, __LINE__, msg ) ;
#define DEBUG_NUM(msg,num) printf ( "    (%s:%d) NUM: %s ->%d\n", \
                __FILE__, __LINE__, msg, num ) ;
#define DEBUG_STR(msg,str) printf ( "    (%s:%d) NUM: %s ->%s\n", \
                __FILE__, __LINE__, msg, str) ;
#define DEBUG_PTR(msg,ptr) printf ( "    (%s:%d) PTR: %s ->%d\n", \
                __FILE__, __LINE__, msg,ptr ) ;
#define DEBUG_VALUE(msg,value) printf ( "    (%s:%d) VALUE: %s -> %s\n", \
                __FILE__, __LINE__, msg, \
                VALUE2STR(rb_funcall(value,rb_intern("inspect"),0)))
#define DEBUG_METHOD(msg,value,method) printf ( "    (%s:%d) METHOD: %s ->
%s\n", \
                __FILE__, __LINE__, msg, \
                VALUE2STR(rb_funcall(value,rb_intern(#method),0)))
#else
#define DEBUG_MSG(msg) ;
#define DEBUG_NUM(msg,num) ;
#define DEBUG_NUM(msg,str) ;
#define DEBUG_PTR(msg,ptr) ;
#define DEBUG_VALUE(msg,value) ;
#define DEBUG_METHOD(msg,value,method) ;
#endif

//
// C++ Namespace
//

using namespace zipios ;

//
// Function prototypes
//

static VALUE ZipLocalEntry_inspect ( VALUE self ) ;
static VALUE ZipLocalEntry_getProperties ( VALUE rbZipLocalEntry ) ;
VALUE ZipLocalEntry_new ( ConstEntryPointer *entry ) ;

static VALUE getDataFromInputStream ( istream *is, int length ) ;
static VALUE ZipFile_getData ( VALUE self, VALUE name ) ;
static VALUE ZipFile_entry ( VALUE self, VALUE name ) ;
static VALUE ZipFile_entries ( VALUE self ) ;
static VALUE ZipFile_inspect ( VALUE self ) ;
VALUE ZipFile_embedded ( VALUE self, VALUE filename ) ;
VALUE ZipFile_new ( int argc, VALUE *argv, VALUE self ) ;

//
// Global Types
//


VALUE mZip;
VALUE cZipFile;
VALUE cZipLocalEntry;

//
// Object 'free' functions used by Data_Wrap_Struct
//

void free_ZipFile(ZipFile *arg) { delete arg ; }
void free_ZipLocalEntry(ZipLocalEntry *arg) { delete arg ; }

//
// ZipEntry#inspect
//

static VALUE ZipLocalEntry_inspect ( VALUE self ) {

    char *buffer ;

    buffer = ALLOCA_N ( char, 1024 ) ;

    snprintf ( buffer, 1024, "#<Zip::ZipEntry:0x%lx @path=\"%s\">",
                self, STR2CSTR(rb_iv_get(self, "@path") ))  ;

    return rb_str_new2(buffer) ;
}

//
// ZipEntry#getProperties
//
// Extract properties from ZipLocalEntry abd write to instance vars
// Method not exposed ro Runy (called by ZipLocalEntry_new)
//

static VALUE ZipLocalEntry_getProperties ( VALUE rbZipLocalEntry ) {

    ZipLocalEntry *zipLocalEntry ;
    Get_ZipLocalEntry ( rbZipLocalEntry, zipLocalEntry ) ;

    rb_iv_set ( rbZipLocalEntry, "@comment",
            rb_str_new2(zipLocalEntry->getComment().c_str()) ) ;
    rb_iv_set ( rbZipLocalEntry, "@compressed_size",
            INT2NUM(zipLocalEntry->getCompressedSize()) ) ;
    rb_iv_set ( rbZipLocalEntry, "@crc",
            INT2NUM(zipLocalEntry->getCrc()) ) ;
    rb_iv_set ( rbZipLocalEntry, "@size",
            INT2NUM(zipLocalEntry->getSize()) ) ;
    rb_iv_set ( rbZipLocalEntry, "@time",
            INT2NUM(zipLocalEntry->getTime()) ) ;
    rb_iv_set ( rbZipLocalEntry, "@isValid",
            zipLocalEntry->isValid() ? Qtrue : Qfalse ) ;
    rb_iv_set ( rbZipLocalEntry, "@isDirectory",
            zipLocalEntry->isDirectory() ? Qtrue : Qfalse ) ;
    rb_iv_set ( rbZipLocalEntry, "@path",
            rb_str_new2(zipLocalEntry->getName().c_str()) ) ;
    rb_iv_set ( rbZipLocalEntry, "@filename",
            rb_str_new2(zipLocalEntry->getFileName().c_str()) ) ;

    return rbZipLocalEntry ;
}

//
// ZipEntry constructor
//
// Passed ConstEntryPointer to C++ ZipLocalEntry object
//

VALUE ZipLocalEntry_new ( ConstEntryPointer *entry ) {

    VALUE rbZipLocalEntry = Qnil ;
    ZipLocalEntry *zipLocalEntry ;

    DEBUG_MSG("Entering Function #ZipLocalEntry_new") ;
    DEBUG_PTR("ConstEntryPointer",entry) ;

    zipLocalEntry = (ZipLocalEntry *) (*entry)->clone() ;

    DEBUG_PTR("zipLocalEntry",zipLocalEntry) ;

    rbZipLocalEntry =  Wrap_ZipLocalEntry ( cZipLocalEntry, zipLocalEntry )
;
    ZipLocalEntry_getProperties ( rbZipLocalEntry ) ;

    DEBUG_VALUE("rbZipLocalEntry",rbZipLocalEntry) ;
    DEBUG_MSG("Leaving Function #ZipLocalEntry_new") ;

    return rbZipLocalEntry ;
}

//
// Extract ZipEntry contents to Ruby string
//

static VALUE getDataFromInputStream ( istream *is, int length ) {

    VALUE data ;
    char *buffer ;

    DEBUG_MSG("Entering Function getDataFromInputStream") ;
    DEBUG_PTR("Istream",is) ;
    DEBUG_NUM("Length",length) ;


    if ( (buffer = (char *) calloc(length,sizeof(char))) == NULL ) {
        rb_raise ( rb_eRuntimeError, "could not allocate buffery memory" ) ;
    }

    try {
        is->read ( buffer,length ) ;
    }
    catch ( exception &excp ) {
        rb_raise ( rb_eRuntimeError, excp.what() ) ;
    }

    data = rb_str_new ( buffer, length ) ;

    DEBUG_METHOD("Got Buffer Length",data,length) ;
    DEBUG_MSG("Leaving Function getDataFromInputStream") ;

    return data ;
}

//
// ZipFile#GetData
//
// Extract uncompressed data for entry 'name' - 'name' can either be a
// ZipEntry value or an explicit path
//
// Calls getDataFromInputStream to extract data
//

static VALUE ZipFile_getData ( VALUE self, VALUE entry ) {

    VALUE rbZipEntry ;
    ZipFile *zf ;
    istream *is ;
    ZipLocalEntry *zipentry ;
    string s_name ;

    DEBUG_MSG("Entering Function #ZipFile_getData") ;
    DEBUG_VALUE("self",self);
    DEBUG_VALUE("entry",entry);

    Get_ZipFile ( self, zf ) ;

    DEBUG_PTR("ZipFile",zf) ;

    try {
        if ( TYPE(entry) == T_STRING ) {
            rbZipEntry = ZipFile_entry ( self, entry) ;
            s_name = STR2CSTR(entry) ;
        }
        else if ( rb_obj_is_kind_of(entry,cZipLocalEntry) ) {
            rbZipEntry = entry ;
            s_name = STR2CSTR(rb_funcall(entry,rb_intern("path"),0)) ;
        }
        else {
            rb_raise ( rb_eTypeError, "Must be String or ZipEntry" ) ;
        }

        DEBUG_PTR("RbZipEntry",rbZipEntry) ;

        Get_ZipLocalEntry ( rbZipEntry, zipentry ) ;

        DEBUG_PTR("ZipEntry",zipentry) ;

        if ( zipentry->isDirectory() ) {
            rb_raise ( rb_eRuntimeError, "Entry is directory" ) ;
        }
        if ( ( is = zf->getInputStream(s_name)) == 0 ) {
            rb_raise ( rb_eRuntimeError, "Could not get istream" ) ;
        }

        DEBUG_PTR("Istream",is) ;

        return getDataFromInputStream ( is, zipentry->getSize() ) ;
    }
    catch ( exception &excp ) {
        rb_raise ( rb_eRuntimeError, excp.what() ) ;
    }
}

//
// ZipFile#entry
//
// Creates ZipEntry object for given entry name
//

static VALUE ZipFile_entry ( VALUE self, VALUE name ) {

    VALUE zipLocalEntry = Qnil ;
    ConstEntryPointer entry ;
    ConstEntryPointer *ptr_entry ;
    ZipFile *zf ;

    const string sname = STR2CSTR(name) ;

    DEBUG_MSG("Entering Function #ZipFile_entry") ;
    DEBUG_VALUE("self",self) ;

    Get_ZipFile ( self, zf ) ;

    DEBUG_PTR("ZipFile",zf) ;

    try {
        if ( (entry = zf->getEntry(sname)) == 0 ) {

            DEBUG_MSG("GetEntry Failed") ;
            rb_raise ( rb_eRuntimeError, "Entry not found" ) ;
        }
        else {

            DEBUG_MSG("GetEntry OK") ;
            ptr_entry = new ConstEntryPointer ( entry ) ;
            DEBUG_PTR("ConstEntryPointer",ptr_entry) ;
            zipLocalEntry = ZipLocalEntry_new ( ptr_entry ) ;
            DEBUG_VALUE("zipLocalEntry",zipLocalEntry) ;
            DEBUG_MSG("Leaving Function #ZipFile_entry") ;

            return zipLocalEntry ;
        }
    }
    catch ( exception &excp ) {

        DEBUG_MSG("Exception") ;
        rb_raise ( rb_eRuntimeError, excp.what() ) ;
    }
}

//
// ZipFile#entries
//
// Creates either list of ZipEntry objects (ZipFile contents) or
// in block context calls block once for each entry passing
// ZipEntry object
//

static VALUE ZipFile_entries ( VALUE self ) {

    VALUE entries_ary ;
    vector< ConstEntryPointer > entries ;
    vector< ConstEntryPointer >::iterator it ;

    ZipFile *zf ;
    Get_ZipFile ( self, zf ) ;

    try {
        entries = zf->entries() ;
    }
    catch ( exception &excp ) {
        rb_raise ( rb_eRuntimeError, excp.what() ) ;
    }

    if ( rb_block_given_p() ) {
        for( it = entries.begin() ; it != entries.end() ; it++) {
            rb_yield ( ZipLocalEntry_new(it) ) ;
        }
        return self ;
    }
    else {
        entries_ary = rb_ary_new () ;
        for( it = entries.begin() ; it != entries.end() ; it++) {
            rb_ary_push ( entries_ary, ZipLocalEntry_new(it) ) ;
        }
        return entries_ary ;
    }
}

//
// ZipFile#size
//
// Returns number of elements in Zipfile
//
//
// static VALUE ZipFile_size ( VALUE self ) {
//
//     ZipFile *zf ;
//     Get_ZipFile ( self, zf ) ;
//     return INT2FIX(zf->size()) ;
// }
//
//
// ZipFile#getName
//
// Returns archive name
//
//
// static VALUE ZipFile_getName ( VALUE self ) {
//
//     ZipFile *zf ;
//     Get_ZipFile ( self, zf ) ;
//     return rb_str_new2(zf->getName().c_str()) ;
// }


//
// ZipFile#inspect
//

static VALUE ZipFile_inspect ( VALUE self ) {

    char *buffer ;

    buffer = ALLOCA_N ( char, 1024 ) ;

    snprintf ( buffer, 1024, "#<Zip::ZipFile:0x%lx @name=\"%s\">",
                self, STR2CSTR(rb_iv_get(self, "@name") ))  ;

    return rb_str_new2(buffer) ;
}

//
// ZipFile#openEmbeddedZipFile
//
// Opens embedded zip file generated according to format in
// zipio++ package (offset stored in last 4 bytes of file)
//

VALUE ZipFile_embedded ( VALUE self, VALUE filename ) {

    ZipFile *zipFile, embeddedZipFile ;
    VALUE rbZipFile = Qnil ;
    VALUE stat ;

    stat = rb_eval_string ( "File" ) ;
    if ( rb_funcall(stat,rb_intern("readable?"),1,filename) == Qfalse ) {
        rb_raise ( rb_eRuntimeError, "Could not open file \"%s\"",
                    STR2CSTR(filename) ) ;
    }

    try {
        embeddedZipFile = ZipFile::openEmbeddedZipFile(STR2CSTR(filename)) ;
        zipFile = new ZipFile ( embeddedZipFile ) ;
    }
    catch ( exception &excp ) {
        rb_raise ( rb_eRuntimeError, excp.what() ) ;
    }

    rbZipFile = Wrap_ZipFile ( self, zipFile ) ;

    return rbZipFile ;
}

//
// ZipFile#new (constructor)
//
//

VALUE ZipFile_new ( int argc, VALUE *argv, VALUE self ) {

    ZipFile zipFile ;
    ZipFile *zipFilePtr ;
    VALUE rbZipFile = Qnil ;
    VALUE stat = Qnil ;
    VALUE filename = Qnil ;
    VALUE offset = Qnil ;
    int c_offset = 0 ;

    rb_scan_args ( argc, argv, "11", &filename, &offset ) ;

    c_offset = ( offset == Qnil ) ? 0 : NUM2INT(offset) ;

    // We have to check the file exists befoew we pass on to the zipios
    // constuctor as it does not generate an expection on error

    stat = rb_eval_string ( "File" ) ;  // Must be a better way to do this

    if ( rb_funcall(stat,rb_intern("readable?"),1,filename) == Qfalse ) {
        rb_raise ( rb_eRuntimeError, "Could not open file \"%s\"",
                    STR2CSTR(filename) ) ;
    }

    try {
        zipFile = ZipFile (STR2CSTR(filename), c_offset) ;
    }
    catch ( exception &excp ) {
        rb_raise ( rb_eRuntimeError, excp.what() ) ;
    }

    // Allocate object on heap once local object successfully created
    // (Seems to prevents memory leak in exception handler)

    zipFilePtr = new ZipFile( zipFile ) ;

    rbZipFile = Wrap_ZipFile ( self, zipFilePtr ) ;
    rb_iv_set ( rbZipFile, "@name",
rb_str_new2(zipFilePtr->getName().c_str()) ) ;
    rb_iv_set ( rbZipFile, "@items", INT2FIX(zipFilePtr->size()) ) ;

    return rbZipFile ;
}

//
// Define methids to Ruby
//

extern "C"
void Init_Zip() {

    mZip = rb_define_module ( "Zip" ) ;

    // ZipFile

    cZipFile = rb_define_class_under ( mZip, "ZipFile",  rb_cObject ) ;

    rb_define_singleton_method ( cZipFile, "new", ZipFile_new, -1 ) ;
    rb_define_singleton_method ( cZipFile, "openEmbeddedZipFile",
ZipFile_embedded, 1 ) ;

    rb_define_method ( cZipFile, "inspect", ZipFile_inspect, 0 ) ;
    rb_define_method ( cZipFile, "entries", ZipFile_entries, 0 ) ;
    rb_define_method ( cZipFile, "entry", ZipFile_entry, 1 ) ;
    rb_define_method ( cZipFile, "getData", ZipFile_getData, 1 ) ;

    rb_define_attr ( cZipFile, "name", 1, 0 ) ;
    rb_define_attr ( cZipFile, "items", 1, 0 ) ;

    // ZipEntry

    cZipLocalEntry = rb_define_class_under ( mZip, "ZipEntry",  rb_cObject )
;

    rb_define_method ( cZipLocalEntry, "inspect", ZipLocalEntry_inspect, 0 )
;

    rb_define_attr ( cZipLocalEntry, "comment", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "compressed_size", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "crc", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "size", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "time", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "isValid?", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "isDirectory?", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "path", 1, 0 ) ;
    rb_define_attr ( cZipLocalEntry, "filename", 1, 0 ) ;

}






In This Thread