1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 | -- Support for segmented things (initially implemented for segmented files).
-- Allows to keep info about an object which is integrally composed of seg-
-- ments.
-- Semantics are:
-- Equal data adjacent segments are merged automatically.
-- No position is without segment.
with Ada.Containers.Ordered_Sets;
generic
type Segment_Data is private;
type Index_Type is range <>;
package Agpl.Segmented_Thing is
pragma Preelaborate;
------------------------------------------------------------------------
-- Object --
------------------------------------------------------------------------
type Object is private;
type Chunk_Type is record
Data : Segment_Data;
First : Index_Type;
Last : Index_Type;
end record;
function "<" (L, R : in Chunk_Type) return Boolean with Inline;
function "=" (L, R : in Chunk_Type) return Boolean with Inline;
------------------------------------------------------------------------
-- Create --
------------------------------------------------------------------------
-- Creates a segmented object with initially a single segment comprending
-- all the object.
-- It's illegal to call any other function without the object
-- having been created.
procedure Create (
This : out Object;
First : in Index_Type;
Last : in Index_Type;
Initial_Data : in Segment_Data);
------------------------------------------------------------------------
-- Count --
------------------------------------------------------------------------
-- Says the number of segments.
function Count (This : in Object) return Natural;
------------------------------------------------------------------------
-- Indexes --
------------------------------------------------------------------------
function First (This : in Object) return Index_Type;
function Last (This : in Object) return Index_Type;
pragma Inline (First, Last);
------------------------------------------------------------------------
-- Get --
------------------------------------------------------------------------
-- Return a numbered piece
-- Warning! cost O (N)
function Get (This : in Object; Index : in Positive) return Chunk_Type;
pragma Inline (Get);
-- This has variable cost: O (1) for sequential advance.
procedure Get (
This : in out Object;
Index : in Positive;
Data : out Chunk_Type);
------------------------------------------------------------------------
-- Get_At --
------------------------------------------------------------------------
-- Return the data at given point
function Get_At (This : in Object; Pos : in Index_Type) return Segment_Data;
pragma Inline (Get_At);
-- Or at a given ratio (1 .. Total):
function Get_At (This : in Object; Offset, Total : in Index_Type) return Segment_Data;
pragma Inline (Get_At);
------------------------------------------------------------------------
-- Set --
------------------------------------------------------------------------
-- Set data for a given segment. Splitting and merging are done if necessary.
-- Last must point to the last element in the segment, not to the first in
-- the next segment.
procedure Set (
This : in out Object;
First : in Index_Type;
Last : in Index_Type;
Data : in Segment_Data);
------------------------------------------------------------------------
-- Debug_Dump --
------------------------------------------------------------------------
generic
with function Image (Data : in Segment_Data) return String is <>;
procedure Debug_Dump (This : in Object);
private
package Ordered_Segments is new Ada.Containers.Ordered_Sets (
Chunk_Type, "<", "=");
function Key (This : in Chunk_Type) return Index_Type; pragma Inline (Key);
function "<" (L : in Index_Type; R : in Chunk_Type) return Boolean;
pragma Inline ("<");
function ">" (L : in Index_Type; R : in Chunk_Type) return Boolean;
pragma Inline (">");
package Ordered_Keys is new Ordered_Segments.Generic_Keys (
Index_Type, Key, "<");
-- Implementation detail: each segment starts at the ending position of the
-- previous, plus one (discrete nature).
type Object is record
Segments : Ordered_Segments.Set;
First : Index_Type;
Last : Index_Type;
-- We use these two to provide a moving cursor in the object and avoid O (n) cost.
Pos : Natural := 0; -- 0 means unpositioned, goes in 1 .. Length (Segments);
Idx : Ordered_Segments.Cursor;
end record;
end Agpl.Segmented_Thing;
|