fixed a buffer growth bug in Replace for Elastic_String
This commit is contained in:
@ -1,19 +1,19 @@
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
package body H3.Strings is
|
||||
BUFFER_ALIGN: constant := 16;
|
||||
BUFFER_ALIGN: constant := 128; -- TODO: change it to a reasonably large value.
|
||||
|
||||
type Shift_Direction is (SHIFT_LEFT, SHIFT_RIGHT);
|
||||
|
||||
function To_Character_Array (Str: in Elastic_String) return Character_Array is
|
||||
function To_Item_Array (Str: in Elastic_String) return Item_Array is
|
||||
begin
|
||||
return Str.Buffer.Slot(Str.Buffer.Slot'First .. Str.Buffer.Last);
|
||||
end To_Character_Array;
|
||||
end To_Item_Array;
|
||||
|
||||
-- return the buffer capacity excluding the terminator
|
||||
function Get_Capacity (Str: in Elastic_String) return System_Size is
|
||||
begin
|
||||
return Str.Buffer.Slot'Length - 1;
|
||||
return Str.Buffer.Slot'Length - Terminator_Length;
|
||||
end Get_Capacity;
|
||||
|
||||
-- private. return the buffer capacity including the terminator
|
||||
@ -38,16 +38,16 @@ package body H3.Strings is
|
||||
return Str.Buffer.Last;
|
||||
end Get_Last_Index;
|
||||
|
||||
function Get_Item (Str: in Elastic_String; Pos: in System_Index) return Character_Type is
|
||||
function Get_Item (Str: in Elastic_String; Pos: in System_Index) return Item_Type is
|
||||
begin
|
||||
return Str.Buffer.Slot(Pos);
|
||||
end Get_Item;
|
||||
|
||||
-- unsafe as it exposes the internal buffer which can go away.
|
||||
-- assume the system address is equal to the thin pointer in size.
|
||||
function Get_Slot_Pointer (Str: in Elastic_String) return Thin_Character_Array_Pointer is
|
||||
function Get_Slot_Pointer (Str: in Elastic_String) return Thin_Item_Array_Pointer is
|
||||
A: System.Address := Str.Buffer.Slot(Str.Buffer.Slot'First)'Address;
|
||||
P: Thin_Character_Array_Pointer;
|
||||
P: Thin_Item_Array_Pointer;
|
||||
for P'Address use A'Address;
|
||||
pragma Import (Ada, P);
|
||||
begin
|
||||
@ -165,7 +165,7 @@ package body H3.Strings is
|
||||
<<COPY_OVER>>
|
||||
if Shift_Pos <= 0 then
|
||||
-- no shift is required. copy the entire string including th
|
||||
Str.Buffer.Slot(First .. Last + 1) := Tmp.Buffer.Slot(First .. Last + 1);
|
||||
Str.Buffer.Slot(First .. Last + Terminator_Length) := Tmp.Buffer.Slot(First .. Last + Terminator_Length);
|
||||
Str.Buffer.Last := Last;
|
||||
return;
|
||||
end if;
|
||||
@ -178,12 +178,12 @@ package body H3.Strings is
|
||||
Mid: System_Size := Shift_Pos - Shift_Size;
|
||||
begin
|
||||
Str.Buffer.Slot(First .. Mid) := Tmp.Buffer.Slot(First .. Mid);
|
||||
Str.Buffer.Slot(Mid + 1 .. Last - Shift_Size + 1) := Tmp.Buffer.Slot(Shift_Pos + 1 .. Last + 1);
|
||||
Str.Buffer.Slot(Mid + 1 .. Last - Shift_Size + Terminator_Length) := Tmp.Buffer.Slot(Shift_Pos + 1 .. Last + Terminator_Length);
|
||||
Str.Buffer.Last := Last - Shift_Size;
|
||||
end;
|
||||
else
|
||||
Str.Buffer.Slot(First .. Shift_Pos - 1) := Tmp.Buffer.Slot(First .. Shift_Pos - 1);
|
||||
Str.Buffer.Slot(Shift_Pos + Shift_Size .. Last + Shift_Size + 1) := Tmp.Buffer.Slot(Shift_Pos .. Last + 1);
|
||||
Str.Buffer.Slot(Shift_Pos + Shift_Size .. Last + Shift_Size + Terminator_Length) := Tmp.Buffer.Slot(Shift_Pos .. Last + Terminator_Length);
|
||||
Str.Buffer.Last := Last + Shift_Size;
|
||||
end if;
|
||||
end Prepare_Buffer;
|
||||
@ -200,7 +200,12 @@ package body H3.Strings is
|
||||
Str.Buffer := Empty_Buffer'Access;
|
||||
end Purge;
|
||||
|
||||
procedure Insert (Str: in out Elastic_String; Pos: in System_Index; V: in Character_Type; Repeat: in System_Size := 1) is
|
||||
function Calc_Inc_Capa (Str: in Elastic_String; Inc: in System_Size) return System_Size is
|
||||
begin
|
||||
return H3.Align(Get_Length(Str) + Inc + Terminator_Length, BUFFER_ALIGN);
|
||||
end Calc_Inc_Capa;
|
||||
|
||||
procedure Insert (Str: in out Elastic_String; Pos: in System_Index; V: in Item_Type; Repeat: in System_Size := 1) is
|
||||
Act_Pos: System_Index := Pos;
|
||||
Act_Inc: System_Size := Repeat;
|
||||
begin
|
||||
@ -208,43 +213,43 @@ package body H3.Strings is
|
||||
Act_Pos := Str.Buffer.Last + 1;
|
||||
end if;
|
||||
|
||||
Prepare_Buffer (Str, H3.Align(Get_Length(Str) + Act_Inc + 1, BUFFER_ALIGN), Act_Pos, Act_Inc);
|
||||
Prepare_Buffer (Str, Calc_Inc_Capa(Str, Act_Inc), Act_Pos, Act_Inc);
|
||||
Str.Buffer.Slot(Act_Pos .. Act_Pos + Act_Inc - 1) := (others => V);
|
||||
end Insert;
|
||||
|
||||
procedure Insert (Str: in out Elastic_String; Pos: in System_Index; V: in Character_Array) is
|
||||
procedure Insert (Str: in out Elastic_String; Pos: in System_Index; V: in Item_Array) is
|
||||
Act_Pos: System_Index := Pos;
|
||||
begin
|
||||
if Act_Pos > Str.Buffer.Last then
|
||||
Act_Pos := Str.Buffer.Last + 1;
|
||||
end if;
|
||||
|
||||
Prepare_Buffer (Str, H3.Align(Get_Length(Str) + V'Length + 1, BUFFER_ALIGN), Act_Pos, V'Length);
|
||||
Prepare_Buffer (Str, Calc_Inc_Capa(Str, V'Length), Act_Pos, V'Length);
|
||||
Str.Buffer.Slot(Act_Pos .. Act_Pos + V'Length - 1) := V;
|
||||
end Insert;
|
||||
|
||||
-- TODO: operator "&" that returns a new Elastic_String
|
||||
procedure Append (Str: in out Elastic_String; V: in Character_Type; Repeat: in System_Size := 1) is
|
||||
procedure Append (Str: in out Elastic_String; V: in Item_Type; Repeat: in System_Size := 1) is
|
||||
begin
|
||||
Insert (Str, Get_Last_Index(Str) + 1, V, Repeat);
|
||||
end Append;
|
||||
|
||||
procedure Append (Str: in out Elastic_String; V: in Character_Array) is
|
||||
procedure Append (Str: in out Elastic_String; V: in Item_Array) is
|
||||
begin
|
||||
Insert (Str, Get_Last_Index(Str) + 1, V);
|
||||
end Append;
|
||||
|
||||
procedure Prepend (Str: in out Elastic_String; V: in Character_Type; Repeat: in System_Size := 1) is
|
||||
procedure Prepend (Str: in out Elastic_String; V: in Item_Type; Repeat: in System_Size := 1) is
|
||||
begin
|
||||
Insert (Str, Get_First_Index(Str), V, Repeat);
|
||||
end Prepend;
|
||||
|
||||
procedure Prepend (Str: in out Elastic_String; V: in Character_Array) is
|
||||
procedure Prepend (Str: in out Elastic_String; V: in Item_Array) is
|
||||
begin
|
||||
Insert (Str, Get_First_Index(Str), V);
|
||||
end Prepend;
|
||||
|
||||
procedure Replace (Str: in out Elastic_String; From_Pos: in System_Index; To_Pos: in System_Size; V: in Character_Type; Repeat: in System_Size := 1) is
|
||||
procedure Replace (Str: in out Elastic_String; From_Pos: in System_Index; To_Pos: in System_Size; V: in Item_Type; Repeat: in System_Size := 1) is
|
||||
Act_To_Pos, Repl_Len: System_Size;
|
||||
begin
|
||||
if From_Pos <= To_Pos and then From_Pos <= Str.Buffer.Last then
|
||||
@ -258,7 +263,7 @@ package body H3.Strings is
|
||||
Prepare_Buffer (Str, Get_Hard_Capacity(Str), Act_To_Pos, Repl_Len - Repeat, SHIFT_LEFT);
|
||||
Act_To_Pos := From_Pos + Repeat - 1;
|
||||
elsif Repeat > Repl_Len then
|
||||
Prepare_Buffer (Str, Get_Hard_Capacity(Str), From_Pos, Repeat - Repl_Len, SHIFT_RIGHT);
|
||||
Prepare_Buffer (Str, Calc_Inc_Capa(Str, Repeat - Repl_Len), From_Pos, Repeat - Repl_Len, SHIFT_RIGHT);
|
||||
Act_To_Pos := From_Pos + Repeat - 1;
|
||||
else
|
||||
Prepare_Buffer (Str);
|
||||
@ -267,7 +272,7 @@ package body H3.Strings is
|
||||
end if;
|
||||
end Replace;
|
||||
|
||||
procedure Replace (Str: in out Elastic_String; From_Pos: in System_Index; To_Pos: in System_Size; V: in Character_Array) is
|
||||
procedure Replace (Str: in out Elastic_String; From_Pos: in System_Index; To_Pos: in System_Size; V: in Item_Array) is
|
||||
Act_To_Pos, Repl_Len: System_Size;
|
||||
begin
|
||||
if From_Pos <= To_Pos and then From_Pos <= Str.Buffer.Last then
|
||||
@ -281,7 +286,7 @@ package body H3.Strings is
|
||||
Prepare_Buffer (Str, Get_Hard_Capacity(Str), Act_To_Pos, Repl_Len - V'Length, SHIFT_LEFT);
|
||||
Act_To_Pos := From_Pos + V'Length - 1;
|
||||
elsif V'Length > Repl_Len then
|
||||
Prepare_Buffer (Str, Get_Hard_Capacity(Str), From_Pos, V'Length - Repl_Len, SHIFT_RIGHT);
|
||||
Prepare_Buffer (Str, Calc_Inc_Capa(Str, V'Length - Repl_Len), From_Pos, V'Length - Repl_Len, SHIFT_RIGHT);
|
||||
Act_To_Pos := From_Pos + V'Length - 1;
|
||||
else
|
||||
Prepare_Buffer (Str);
|
||||
@ -307,7 +312,7 @@ package body H3.Strings is
|
||||
return Str.Buffer = Str2.Buffer or else Str.Buffer.Slot(Get_First_Index(Str) .. Get_Last_Index(Str)) = Str2.Buffer.Slot(Get_First_Index(Str2) .. Get_Last_Index(Str2));
|
||||
end "=";
|
||||
|
||||
function "=" (Str: in Elastic_String; Str2: in Character_Array) return Standard.Boolean is
|
||||
function "=" (Str: in Elastic_String; Str2: in Item_Array) return Standard.Boolean is
|
||||
begin
|
||||
return Str.Buffer.Slot(Get_First_Index(Str) .. Get_Last_Index(Str)) = Str2;
|
||||
end "=";
|
||||
@ -331,4 +336,5 @@ package body H3.Strings is
|
||||
begin
|
||||
Unref_Buffer (Str.Buffer);
|
||||
end Finalize;
|
||||
|
||||
end H3.Strings;
|
||||
|
Reference in New Issue
Block a user