Contents   Index   Search   Previous   Next
 B.3.2 The Generic Package Interfaces.C.Pointers
1
   The generic package Interfaces.C.Pointers allows
the Ada programmer to perform C-style operations on pointers. It includes
an access type Pointer, Value functions that dereference a Pointer and
deliver the designated array, several pointer arithmetic operations,
and ``copy'' procedures that copy the contents of a source pointer into
the array designated by a destination pointer. As in C, it treats an
object Ptr of type Pointer as a pointer to the first element of an array,
so that for example, adding 1 to Ptr yields a pointer to the second element
of the array.
2
   The generic allows two styles of usage: one in
which the array is terminated by a special terminator element; and another
in which the programmer needs to keep track of the length. 
Static Semantics
3
   The generic library
package Interfaces.C.Pointers has the following declaration: 
4
generic
   type Index is (<>);
   type Element is private;
   type Element_Array is array (Index range <>) of aliased Element;
   Default_Terminator : Element;
package Interfaces.C.Pointers is
   pragma Preelaborate(Pointers); 
5
   type Pointer is access all Element; 
6
   function Value(Ref        : in Pointer;
                  Terminator : in Element := Default_Terminator)
      return Element_Array; 
7
   function Value(Ref    : in Pointer;
                  Length : in ptrdiff_t)
      return Element_Array; 
8
   Pointer_Error : exception; 
9
   -- C-style Pointer arithmetic
10
   function "+" (Left : in Pointer;   Right : in ptrdiff_t) return Pointer;
   function "+" (Left : in ptrdiff_t; Right : in Pointer)   return Pointer;
   function "-" (Left : in Pointer;   Right : in ptrdiff_t) return Pointer;
   function "-" (Left : in Pointer;   Right : in Pointer) return ptrdiff_t;
11
   procedure Increment (Ref : in out Pointer);
   procedure Decrement (Ref : in out Pointer); 
12
   pragma Convention (Intrinsic, "+");
   pragma Convention (Intrinsic, "-");
   pragma Convention (Intrinsic, Increment);
   pragma Convention (Intrinsic, Decrement);
13
   function Virtual_Length (Ref        : in Pointer;
                            Terminator : in Element := Default_Terminator)
      return ptrdiff_t; 
14
   procedure Copy_Terminated_Array
      (Source     : in Pointer;
       Target     : in Pointer;
       Limit      : in ptrdiff_t := ptrdiff_t'Last;
       Terminator : in Element :=  Default_Terminator); 
15
   procedure Copy_Array (Source  : in Pointer;
                         Target  : in Pointer;
                         Length  : in ptrdiff_t); 
16
end Interfaces.C.Pointers;
17
    The type Pointer
is C-compatible and corresponds to one use of C's ``Element *''. An object
of type Pointer is interpreted as a pointer to the initial Element in
an Element_Array. Two styles are supported: 
18
- Explicit termination of an array value
with Default_Terminator (a special terminator value);
 
19
- Programmer-managed
length, with Default_Terminator treated simply as a data element. 
 
20
function Value(Ref        : in Pointer;
               Terminator : in Element := Default_Terminator)
   return Element_Array;
21
This function
returns an Element_Array whose value is the array pointed to by Ref,
up to and including the first Terminator; the lower bound of the array
is Index'First. Interfaces.C.Strings.Dereference_Error is propagated
if Ref is null.
22
function Value(Ref    : in Pointer;
               Length : in ptrdiff_t)
   return Element_Array;
23
This function
returns an Element_Array comprising the first Length elements pointed
to by Ref. The exception Interfaces.C.Strings.Dereference_Error is propagated
if Ref is null. 
24
    The "+"
and "-" functions perform arithmetic on Pointer values, based
on the Size of the array elements. In each of these functions, Pointer_Error
is propagated if a Pointer parameter is null. 
25
procedure Increment (Ref : in out Pointer);
26
Equivalent to
Ref := Ref+1.
27
procedure Decrement (Ref : in out Pointer);
28
Equivalent to
Ref := Ref-1.
29
function Virtual_Length (Ref        : in Pointer;
                         Terminator : in Element := Default_Terminator)
   return ptrdiff_t;
30
Returns the number
of Elements, up to the one just before the first Terminator, in Value(Ref,
Terminator).
31
procedure Copy_Terminated_Array
   (Source     : in Pointer;
    Target     : in Pointer;
    Limit      : in ptrdiff_t := ptrdiff_t'Last;
    Terminator : in Element := Default_Terminator);
32
This procedure
copies Value(Source, Terminator) into the array pointed to by Target;
it stops either after Terminator has been copied, or the number of elements
copied is Limit, whichever occurs first. Dereference_Error is propagated
if either Source or Target is null. 
33
procedure Copy_Array (Source  : in Pointer;
                      Target  : in Pointer;
                      Length  : in ptrdiff_t);
34
This procedure copies the first Length elements
from the array pointed to by Source, into the array pointed to by Target.
Dereference_Error is propagated if either Source or Target is null.
Erroneous Execution
35
    It is erroneous to dereference
a Pointer that does not designate an aliased Element. 
 
36
    Execution of Value(Ref, Terminator)
is erroneous if Ref does not designate an aliased Element in an Element_Array
terminated by Terminator.
 
37
    Execution of Value(Ref, Length)
is erroneous if Ref does not designate an aliased Element in an Element_Array
containing at least Length Elements between the designated Element and
the end of the array, inclusive.
 
38
    Execution of Virtual_Length(Ref,
Terminator) is erroneous if Ref does not designate an aliased Element
in an Element_Array terminated by Terminator.
 
39
    Execution
of Copy_Terminated_Array(Source, Target, Limit, Terminator) is erroneous
in either of the following situations: 
 
40
- Execution of both Value(Source,Terminator)
and Value(Source,Limit) are erroneous, or
 
41
- Copying writes past the end of the
array containing the Element designated by Target. 
 
42
    Execution of Copy_Array(Source,
Target, Length) is erroneous if either Value(Source, Length) is erroneous,
or copying writes past the end of the array containing the Element designated
by Target. 
 
43
14  To
compose a Pointer from an Element_Array, use 'Access on the first element.
For example (assuming appropriate instantiations): 
44
Some_Array   : Element_Array(0..5) ;
Some_Pointer : Pointer := Some_Array(0)'Access;
Examples
45
    Example of Interfaces.C.Pointers:
46
with Interfaces.C.Pointers;
with Interfaces.C.Strings;
procedure Test_Pointers is
   package C renames Interfaces.C;
   package Char_Ptrs is
      new C.Pointers (Index              => C.size_t,
                      Element            => C.char,
                      Element_Array      => C.char_array,
                      Default_Terminator => C.nul);
47
   use type Char_Ptrs.Pointer;
   subtype Char_Star is Char_Ptrs.Pointer;
48
   procedure Strcpy (Target_Ptr, Source_Ptr : Char_Star) is
      Target_Temp_Ptr : Char_Star := Target_Ptr;
      Source_Temp_Ptr : Char_Star := Source_Ptr;
      Element : C.char;
   begin
      if Target_Temp_Ptr = null or Source_Temp_Ptr = null then
         raise C.Strings.Dereference_Error;
      end if;
49/1
      loop
         Element             := Source_Temp_Ptr.all;
         Target_Temp_Ptr.all := Element;
         exit when C."="(Element, C.nul);
         Char_Ptrs.Increment(Target_Temp_Ptr);
         Char_Ptrs.Increment(Source_Temp_Ptr);
      end loop;
   end Strcpy;
begin
   ...
end Test_Pointers;
Contents   Index   Search   Previous   Next   Legal