----------------------------------------------------------------------------- -- -- Onions Network Streams Library -- -- O N I O N S . B U C K E T S -- -- S p e c -- -- Copyright (C) 1997-1998 Regents of the University of California -- -- Onions is free software; you can redistribute it and/or modify it under -- the terms of the GNU General Public License as published by the Free -- Software Foundation, with or without the single exception listed below; -- either version 2, or (at your option) any later version. Onions is -- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -- PARTICULAR PURPOSE. See the GNU General Public License for more details. -- You should have received a copy of the GNU General Public License -- distributed with Onions; see the file COPYING. If not, write to the -- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA -- 02111-1307, USA. -- -- As a special exception, if other files instantiate generics from this -- library, or you link this library with other files to produce an -- executable, this library does not by itself cause the resulting -- executable to be covered by the GNU General Public License. This -- exception does not however invalidate any other reasons why the -- executable file might be covered by the GNU General Public License. -- -- Created in 1997 by Roy T. Fielding ----------------------------------------------------------------------------- -- -- The Onions Buckets ADT defines objects and operations for manipulating -- raw data in the form of Iovec structures (a system address and length). -- The primary advantage of using Buckets instead of Strings or -- Storage_Arrays or Stream_Element_Arrays or C.char_arrays is that we can -- control their memory structure without worrying about the dope vector, -- avoid unnecessary copies, and perform more efficient moves to other data -- structures. -- -- Ada95 has a serious flaw in its design in that it provides several -- useful predefined types (like Unbounded_Strings), but doesn't provide -- any access to the memory location/structure of the data represented -- by those types. You might say "but that's a good thing, since it provides -- for data abstraction" and I would agree; unfortunately, Ada95 also fails -- to provide any real interface to the operating system (unlike other modern -- languages like Perl, Python, Java, etc.) and thus the programmer must -- provide their own interface, and therefore the systems programmer must -- know the compiler's internal memory structure for the predefined type -- or invent their own type to replace the predefined type. The result -- is that an Ada95 systems program is constantly copying data from variables -- of one type to another, which guarantees that an Ada95 implementation -- will be less efficient than just about any other language. -- with Ada.Streams; use Ada.Streams; with Interfaces.C.Strings; with System.Storage_Elements; use System.Storage_Elements; with Onions.List_Queues; with Onions.Thin; package Onions.Buckets is type Bucket_Rec is private; type Bucket is access Bucket_Rec; package Bucket_Queues is new Onions.List_Queues (Bucket); subtype Bucket_List is Bucket_Queues.List; subtype Bucket_Brigade is Bucket_Queues.Queue; -- Ada95 is lame; the following should be predefined -- type String_Access is access String; -- Allocate storage for a Bucket of a given size. -- function Allocate (Size : in Storage_Count) return Bucket; -- Free the storage associated with a Bucket. -- procedure Free (Bucko : in out Bucket); procedure Free (Blist : in out Bucket_List); -- Split a Bucket into two Buckets, Front and Back, discarding anything -- in the gaps around the two offsets (a common thing for filters). -- -- I wanted to use dynamically-determined defaults for the last -- four parameters, but Ada95 won't let me. They would have been -- -- Fbeg : in Storage_Offset := 0; -- Flen : in Storage_Count := Bbeg ? Bbeg - Fbeg : 0; -- Bbeg : in Storage_Offset := Fbeg + Flen; -- Blen : in Storage_Count := Bucko.Iov_Len - Bbeg; -- -- so you'll have to do that manually now. -- procedure Split (Bucko : in out Bucket; Front : out Bucket; Back : out Bucket; Fbeg : in Storage_Offset; Flen : in Storage_Count; Bbeg : in Storage_Offset; Blen : in Storage_Count); -- Likewise, the address-based defaults would have been -- -- Fbeg : in System.Address := Null_Address; -- Flen : in Storage_Count := Bbeg ? Bbeg - Fbeg : 0; -- Bbeg : in System.Address := Fbeg + Flen; -- Blen : in Storage_Count := (Bucko.Iov_Base+Bucko.Iov_Len)-Bbeg; -- procedure Split (Bucko : in out Bucket; Front : out Bucket; Back : out Bucket; Fbeg : in System.Address; Flen : in Storage_Count; Bbeg : in System.Address; Blen : in Storage_Count); -- Truncate a Bucket beyond a given length -- procedure Truncate (Bucko : in out Bucket; Len : in Storage_Count); -- To_Iovec sets an Iovec structure to point to a bucket's contents. -- procedure To_Iovec (Bucko : in Bucket; Vec : in Onions.Thin.Iovec_Access); -- Address_Of returns the System.Address of the bucket's contents. -- function Address_Of (Bucko : Bucket) return System.Address; -- Get or Set a Character value at a given address -- function Val (Addr : System.Address) return Character; procedure Set (Addr : System.Address; Char : Character); -- To_Ada returns (copies) the data of a bucket to the given array type -- function To_Ada (Bucko : in Bucket) return String; function To_Ada (Bucko : in Bucket) return Wide_String; function To_Ada (Bucko : in Bucket) return C.char_array; function To_Ada (Bucko : in Bucket) return C.Strings.chars_ptr; function To_Ada (Bucko : in Bucket) return Storage_Array; function To_Ada (Bucko : in Bucket) return Stream_Element_Array; -- New_Bucket allocates a new bucket containing a copy of an array. -- function New_Bucket (S : in String) return Bucket; function New_Bucket (S : in Wide_String) return Bucket; function New_Bucket (S : in C.char_array) return Bucket; function New_Bucket (S : in Storage_Array) return Bucket; function New_Bucket (S : in Stream_Element_Array) return Bucket; function New_Bucket (S : in Stream_Element_Array; Last : in Stream_Element_Offset) return Bucket; function New_Bucket (S : in C.Strings.chars_ptr; Len : in C.size_t) return Bucket; function New_Bucket (S : in System.Address; Len : in Storage_Count) return Bucket; function New_Bucket (S : in Character) return Bucket; -- Dump_Into dumps the contents of a bucket list into an array -- until the array is full or the buckets are empty. Last is -- the array position of the last byte filled. Assumes the -- bucket list is non-empty and that Last < Item'Last on entry. -- Note that Item may already contain preprocessed data. -- procedure Dump_Into (BL : in out Bucket_List; Item : in out Stream_Element_Array; Last : in out Stream_Element_Offset); -- Dump_Line dumps the contents of one bucket list (Foil) into -- another list (Toil) until an End-of-Line character sequence -- (CRLF, bare LF, or bare CR) is found (Done = True) or we run -- out of bucket contents. The End-of-Line character sequence is -- translated to LF. Assumes Foil is non-empty on entry. -- Note that Toil may contain previously processed data. -- procedure Dump_Line (Foil : in out Bucket_List; Toil : in out Bucket_List; Done : out Boolean); -- Chop the last character from a bucket or list of buckets. -- Normally used to remove the LF from a complete line. -- procedure Chop (Blist : Bucket_List); procedure Chop (Bucko : Bucket); -- Combine all buckets in a bucket list into a single bucket or string. -- procedure Combine (Blist : in out Bucket_List; Combo : out Bucket); procedure Combine (Blist : in out Bucket_List; Combo : out String_Access); -- Trim a list of buckets into two lists beyond a number of bytes. -- Do not worry about retaining the data beyond those bytes. -- procedure Trim (Bytes : in Storage_Count; Front : in Bucket_List; Back : out Bucket_List); -- Get_Size determines the number of buckets, and total bytes within -- those buckets, from a bucket list. -- procedure Get_Size (Blist : in Bucket_List; Bucks : out Natural; Bytes : out Storage_Count); private type Bucket_Rec is record Iov_Base : System.Address; -- equivalent to (void *) Iov_Len : Storage_Count; -- equivalent to C.size_t end record; end Onions.Buckets;