From: Olivier Scalbert <olivier.scalbert@algosyn.com>
Subject: Re: Load an object from a file
Date: Thu, 09 Apr 2009 22:32:57 +0200
Date: 2009-04-09T22:32:57+02:00 [thread overview]
Message-ID: <49de5b78$0$2853$ba620e4c@news.skynet.be> (raw)
In-Reply-To: <443d72ca-5bbd-46a3-84c6-e8bd984e5b80@k41g2000yqh.googlegroups.com>
Hi,
I still have one question ...
How can I implement the Load_Class procedure that will use the Input
function?
I do not know how to get the needed stream from a given file name.
And I do not know how to define the Class_File_Structure result (I get
an unconstrained subtype (need initialization)).
Thanks,
Olivier
Here is my spec:
--------------------------
package jvm is
type Byte_T is range 0..255;
for Byte_T'Size use 8;
type U2_T is range 0 .. 2 ** 16 - 1;
type U4_T is range 0 .. 2 ** 32 - 1;
type cp_info_T is new Integer; -- Just for test !
type Constant_Pool_Array_T is array (U2_T range <>) of cp_info_T;
type Class_File_Structure_T(
constant_pool_count,
interfaces_count,
fields_count,
methods_count,
attributes_count : U2_T) is record
Magic : U4_T;
Minor_Version : U2_T;
Major_Version : U2_T;
Constant_Pool : Constant_Pool_Array_T (2 .. constant_pool_count);
--interfaces : Interfaces_Array_T (1 .. interfaces_count);
end record;
procedure Run;
procedure Load_Class(File_Name: String);
function Input(Stream : not null access
Ada.Streams.Root_Stream_Type'Class)
return Class_File_Structure_T; -- see RM 13.13(22)
and following
for Class_File_Structure_T'Input use Input; -- as per RM 13.13(38/2)
end jvm;
Here is the body:
--------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Sequential_IO;
with Ada.Unchecked_Deallocation;
package body jvm is
procedure run is
begin
Load_Class("Main.class");
end run;
procedure Load_Class(File_Name: String) is
Class_File_Structure: Class_File_Structure_T; -- (unconstrained
subtype (need initialization)
begin
Put_Line(File_Name);
Class_file_Structure := Input(Stream ???);
end Load_Class;
function Input(Stream : not null access
Ada.Streams.Root_Stream_Type'Class)
return Class_File_Structure_T is
Magic : U4_T;
Minor_Version : U2_T;
Major_Version : U2_T;
Constant_Pool_Count : U2_T;
type Constant_Pool_Array_Access is access Constant_Pool_Array_T;
procedure Free is new Ada.Unchecked_Deallocation
(Constant_Pool_Array_T, Constant_Pool_Array_Access);
Constant_Pool : Constant_Pool_Array_Access;
begin
-- Read
U4_T'Read(Stream, Magic);
U2_T'Read(Stream, Minor_Version);
U2_T'Read(Stream, Major_Version);
U2_T'Read (Stream, Constant_Pool_Count);
Constant_Pool := new Constant_Pool_Array_T (1 ..
Constant_Pool_Count - 1);
Constant_Pool_Array_T'Read (Stream, Constant_Pool.all);
-- Fill in to the result
declare
Result : Class_File_Structure_T
(constant_pool_count => Constant_Pool_Count,
interfaces_count => 0, --Interfaces_Count,
fields_count => 0, --Fields_Count,
methods_count => 0, --Methods_Count,
attributes_count => 0); --Attricutes_Count);
begin
Result.Magic := Magic;
Result.Minor_Version := Minor_Version;
Result.Major_Version := Major_Version;
Result.Constant_Pool := Constant_Pool.all;
Free(Constant_Pool);
return Result;
end;
end;
end jvm;
Ludovic Brenta wrote:
> Olivier Scalbert wrote on comp.lang.ada:
>> Hello everybody !
>>
>> In my Ada self-study context, I was asking myself how can I create and
>> fill objects or records from a file.
>> As an example, I have tried to represent a java class file format
>> structure and fill it with a .class java file.
>>
>> The ClassFile structure is something like:
>>
>> ClassFile {
>> u4 magic;
>> u2 minor_version;
>> u2 major_version;
>> u2 constant_pool_count;
>> cp_info constant_pool[constant_pool_count-1];
>> u2 access_flags;
>> u2 this_class;
>> u2 super_class;
>> u2 interfaces_count;
>> u2 interfaces[interfaces_count];
>> u2 fields_count;
>> field_info fields[fields_count];
>> u2 methods_count;
>> method_info methods[methods_count];
>> u2 attributes_count;
>> attribute_info attributes[attributes_count];
>> }
>>
>> JVM Specs can be found there:http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc...
>>
>> I have no problem to represent and to fill from file, the first four fields.
>> But I do not know what is the best (Ada) way of representing the array
>> of info constant_pool as the size is only known at run time.(=
>> constant_pool_cout).
>
> I would create a record type with one discriminant for each array,
> like so:
>
> type Constant_Pool_Array is array (Positive range <>) of cp_info;
> type Interfaces_Array is array (Positive range <>) of u2;
> -- etc.
>
> type Class_File
> (constant_pool_count,
> interfaces_count,
> fields_count,
> methods_count,
> attributes_count : u2)
> is record
> ...
> constant_pool : Constant_Pool_Array (2 .. constant_pool_count);
> ...
> interfaces : Interfaces_Array (1 .. interfaces_count);
> ... etc.
> end record;
>
>> Also how can I fill this array ?
>
> You would normally simply call the predefined Class_File'Read but this
> wouldn't work since the order of the components in type Class_File
> does not match the order in the file. So, you'd specify your own Read:
>
> function Input(
> Stream : not null access Ada.Streams.Root_Stream_Type'Class)
> return Class_File); -- see RM 13.13(22) and following
> for Class_File'Input use Input; -- as per RM 13.13(38/2)
>
> function Input(
> Stream : not null access Ada.Streams.Root_Stream_Type'Class)
> return Class_File)
> is
> Constant_Pool_Count : u2;
> type Constant_Pool_Array_Access is access Constant_Pool_Array;
> procedure Free is new Ada.Unchecked_Deallocation
> (Constant_Pool_Array, Constant_Pool_Array_Access);
> Constant_Pool : Constant_Pool_Array_Access;
> begin
> ...
> u2'Read (Stream, Constant_Pool_Count);
> Constant_Pool := new Constant_Pool_Array (1 .. Constant_Pool - 1);
> Constant_Pool_Array'Read (Stream, Constant_Pool.all);
> ...
>
> After reading all members, construct the result:
>
> declare
> Result : Class_File
> (constant_pool_count => Constant_Pool_Count,
> interfaces_count => Interfaces_Count,
> fields_count => Fields_Count,
> methods_count => Methods_Count,
> attributes_count => Attricutes_Count);
> begin
> Result.Constant_Pool := Constant_Pool.all;
> ...
> Free (Constant_Pool);
> ...
> return Result;
> end;
> end Input;
>
> You can also eliminate the use of access types and dynamic allocation
> and deallocation by nesting declare blocks, e.g.
>
> u2'Read (Stream, Constant_Pool_Count);
> declare
> Constant_Pool : Constant_Pool_Array (1 .. Constant_Pool_Count);
> begin
> Constant_Pool_Array'Read (Stream, Constant_Pool);
> ...
> u2'Read (Stream, Interfaces_Count);
> declare
> Interfaces : Interfaces_Count_Array (1 .. Interfaces_Count);
> begin
> ...
> end;
> end;
>
> HTH
>
> --
> Ludovic Brenta.
next prev parent reply other threads:[~2009-04-09 20:32 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-03 12:01 Load an object from a file Olivier Scalbert
2009-04-03 13:07 ` Niklas Holsti
2009-04-03 13:37 ` Ludovic Brenta
2009-04-03 15:19 ` Olivier Scalbert
2009-04-03 16:08 ` Georg Bauhaus
2009-04-03 16:22 ` Ludovic Brenta
2009-04-03 16:41 ` Olivier Scalbert
2009-04-03 16:46 ` Adam Beneschan
2009-04-03 20:22 ` Ludovic Brenta
2009-04-09 20:32 ` Olivier Scalbert [this message]
2009-04-09 21:22 ` Ludovic Brenta
2009-04-09 22:22 ` Olivier Scalbert
2009-04-19 13:08 ` Olivier Scalbert
2009-04-19 19:52 ` Ludovic Brenta
2009-04-19 20:27 ` Gautier
2009-04-03 13:41 ` Thomas Løcke
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox