Replaced Ustring_List with Ada.Containers.
During randomization, Indefinite_Vectors.Swap should swap references more
efficiently than with Unbounded_String assignments and reallocation.
nicolas.boulenguez
14 years ago
0 | * CODING | |
1 | - replace local vector tool by Ada.Containers.Vectors | |
2 | 0 | * TRANSLATION |
3 | 1 | - -i message to translate |
6 | 6 | |
7 | 7 | with Support_Routines; use Support_Routines; |
8 | 8 | with Intl; use Intl; |
9 | with UString_List; use UString_List; | |
10 | 9 | |
11 | 10 | procedure Music123 is |
12 | 11 | Arg_Num : Positive; |
17 | 16 | Option_Eternal_Random : Boolean := False; |
18 | 17 | Option_Ignore_Extension_Case : Boolean := False; |
19 | 18 | Delay_Length : Duration := 0.5; |
20 | File_List : UString_List.Vector := New_Vector; | |
19 | File_List : UString_List.Vector; | |
21 | 20 | Program_List : Tool_List.Vector; |
22 | 21 | |
23 | 22 | function N (Msg : String) return String renames Gettext; |
87 | 86 | if Check_Filename (Argument (I), |
88 | 87 | Program_List, |
89 | 88 | Option_Ignore_Extension_Case) then |
90 | Append (File_List, To_Unbounded_String (Argument (I))); | |
89 | File_List.Append (Argument (I)); | |
91 | 90 | end if; |
92 | 91 | end loop; |
93 | 92 | Arg_Num := Argument_Count + 1; |
98 | 97 | if Check_Filename (Argument (Arg_Num), |
99 | 98 | Program_List, |
100 | 99 | Option_Ignore_Extension_Case) then |
101 | Append (File_List, To_Unbounded_String (Argument (Arg_Num))); | |
100 | File_List.Append (Argument (Arg_Num)); | |
102 | 101 | end if; |
103 | 102 | end if; |
104 | 103 | Arg_Num := Arg_Num + 1; |
239 | 239 | Error (Error_String); |
240 | 240 | raise Noted_Error; |
241 | 241 | end if; |
242 | I := 1; | |
243 | while I <= Length (File_List) loop | |
244 | declare | |
245 | Current_File : constant String := To_String (Get (File_List, I)); | |
242 | I := File_List.First_Index; | |
243 | while I <= File_List.Last_Index loop | |
244 | declare | |
245 | Current_File : constant String := File_List.Element (I); | |
246 | 246 | begin |
247 | 247 | if not File_Exists (Current_File) then |
248 | Remove (File_List, I); | |
248 | File_List.Delete (I); | |
249 | 249 | I := I - 1; |
250 | 250 | elsif Is_Directory (Current_File) then |
251 | 251 | begin |
252 | Remove (File_List, I); | |
252 | File_List.Delete (I); | |
253 | 253 | I := I - 1; |
254 | 254 | if Option_Recurse then |
255 | 255 | Open (Current_Directory, Current_File); |
274 | 274 | Extension_List, |
275 | 275 | Option_Ignore_Extension_Case) |
276 | 276 | then |
277 | Append (File_List, | |
278 | To_Unbounded_String (Full_Name)); | |
277 | File_List.Append (Full_Name); | |
279 | 278 | end if; |
280 | 279 | end; |
281 | 280 | end if; |
290 | 289 | I := I + 1; |
291 | 290 | end; |
292 | 291 | end loop; |
293 | if Empty (File_List) then | |
292 | if File_List.Is_Empty then | |
294 | 293 | Error (N ("No valid filenames found.")); |
295 | 294 | raise Noted_Error; |
296 | 295 | end if; |
299 | 298 | |
300 | 299 | procedure Randomize_Names (File_List : in out UString_List.Vector) is |
301 | 300 | |
302 | A, B : Unbounded_String; | |
303 | J : UString_List.Index; | |
301 | J : Positive; | |
304 | 302 | Gen : Generator; |
305 | Len : constant Integer := Length (File_List); | |
306 | 303 | begin |
307 | 304 | Reset (Gen, Integer (Seconds (Clock) * 10.0)); |
308 | 305 | -- From Knuth, TAOCP vol. 2, edition 3, page 146, 3.4.2, algorithm P |
309 | for I in reverse 2 .. Len loop | |
310 | J := Integer (Float'Floor (Random (Gen) * Float (I))) + 1; | |
311 | A := Get (File_List, I); | |
312 | B := Get (File_List, J); | |
313 | Set (File_List, I, B); | |
314 | Set (File_List, J, A); | |
306 | for I in reverse File_List.First_Index + 1 .. File_List.Last_Index loop | |
307 | J := Integer | |
308 | (Float'Floor (Random (Gen) | |
309 | * Float (I + File_List.First_Index - 1))) | |
310 | + File_List.First_Index; | |
311 | File_List.Swap (I, J); | |
315 | 312 | end loop; |
316 | 313 | end Randomize_Names; |
317 | 314 | |
341 | 338 | Option_Eternal_Random : in Boolean; |
342 | 339 | Option_Ignore_Extension_Case : in Boolean |
343 | 340 | ) is |
344 | ||
345 | Gen : Generator; | |
346 | Len : Integer; | |
347 | 341 | |
348 | 342 | use Interfaces.C; |
349 | 343 | function System (Command : char_array) return Integer; |
381 | 375 | end if; |
382 | 376 | end Play_A_Song; |
383 | 377 | |
378 | Gen : Generator; | |
384 | 379 | begin |
385 | 380 | if Option_Eternal_Random then |
386 | Len := Length (File_List); | |
387 | 381 | Reset (Gen, Integer (Seconds (Clock) * 10.0)); |
388 | 382 | declare |
389 | Song_Number : Integer; | |
383 | Len : constant Natural | |
384 | := File_List.Last_Index - File_List.First_Index + 1; | |
385 | Song_Number : Positive; | |
390 | 386 | begin |
391 | 387 | loop |
392 | 388 | Song_Number := |
393 | 389 | Integer (Float'Floor (Random (Gen) * Float (Len))) + 1; |
394 | Play_A_Song (To_String (Get (File_List, Song_Number)), | |
390 | Play_A_Song (File_List.Element (Song_Number), | |
395 | 391 | Option_Quiet); |
396 | 392 | end loop; |
397 | 393 | end; |
402 | 398 | end if; |
403 | 399 | |
404 | 400 | <<Loop_Start>> null; |
405 | for I in 1 .. Length (File_List) loop | |
406 | Play_A_Song (To_String (Get (File_List, I)), Option_Quiet); | |
401 | for I in File_List.First_Index .. File_List.Last_Index loop | |
402 | Play_A_Song (File_List.Element (I), Option_Quiet); | |
407 | 403 | delay (Delay_Length); |
408 | 404 | end loop; |
409 | 405 | if Option_Loop then |
429 | 425 | Ada.Strings.Both); |
430 | 426 | begin |
431 | 427 | if Line /= "" and then Line (1) /= '#' then |
432 | Append (File_List, To_Unbounded_String (Line)); | |
428 | File_List.Append (Line); | |
433 | 429 | end if; |
434 | 430 | end; |
435 | 431 | end loop; |
0 | 0 | with Ada.Containers.Vectors; |
1 | with UString_List; use UString_List; | |
1 | with Ada.Containers.Indefinite_Vectors; | |
2 | 2 | with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; |
3 | 3 | with Intl; |
4 | 4 | |
5 | 5 | package Support_Routines is |
6 | ||
7 | package UString_List is new Ada.Containers.Indefinite_Vectors | |
8 | (Positive, String); | |
6 | 9 | |
7 | 10 | function N (Msg : String) return String renames Intl.Gettext; |
8 | 11 |
0 | with Vector; | |
1 | with Ada.Strings.Unbounded; | |
2 | ||
3 | package UString_List is new Vector (Ada.Strings.Unbounded.Unbounded_String); |
0 | with Ada.Unchecked_Deallocation; | |
1 | ||
2 | package body Vector is | |
3 | -- if Debug then checks end if; must be constant to be optimized properly | |
4 | -- which is the only point of Debug := False. | |
5 | Debug : constant Boolean := True; | |
6 | function Advance_N (Start : Index; Times : Integer) return Index; | |
7 | ||
8 | procedure Delete is new Ada.Unchecked_Deallocation (Real_Vector, RV_Access); | |
9 | ||
10 | function New_Vector return Vector is | |
11 | New_Real_Length : constant Index := Advance (0); | |
12 | New_Vect : Vector; | |
13 | begin | |
14 | New_Vect.Vect := new Real_Vector (1 .. New_Real_Length); | |
15 | New_Vect.Length := 0; | |
16 | New_Vect.Real_Length := New_Real_Length; | |
17 | return New_Vect; | |
18 | end New_Vector; | |
19 | ||
20 | procedure Init (New_Vect : out Vector) is | |
21 | New_Real_Length : constant Index := Advance (0); | |
22 | begin | |
23 | New_Vect.Vect := new Real_Vector (1 .. New_Real_Length); | |
24 | New_Vect.Length := 0; | |
25 | New_Vect.Real_Length := New_Real_Length; | |
26 | end Init; | |
27 | ||
28 | procedure Reinit (Vect : in out Vector) is | |
29 | New_Real_Length : constant Index := Advance (0); | |
30 | begin | |
31 | Delete (Vect.Vect); | |
32 | Vect.Vect := new Real_Vector (1 .. New_Real_Length); | |
33 | Vect.Length := 0; | |
34 | Vect.Real_Length := New_Real_Length; | |
35 | end Reinit; | |
36 | ||
37 | function Advance_N (Start : Index; Times : Integer) return Index is | |
38 | Final_Size : Index := Start; | |
39 | begin | |
40 | for I in 1 .. Times loop | |
41 | Final_Size := Advance (Final_Size); | |
42 | end loop; | |
43 | return Final_Size; | |
44 | end Advance_N; | |
45 | pragma Inline (Advance_N); | |
46 | ||
47 | procedure Expand (Vect : in out Vector; Times : Integer := 1) is | |
48 | New_Real_Length : constant Index := Advance_N (Vect.Real_Length, Times); | |
49 | NRV_Access : RV_Access; | |
50 | begin | |
51 | NRV_Access := new Real_Vector (1 .. New_Real_Length); | |
52 | for I in 1 .. Vect.Length loop | |
53 | NRV_Access.all (I) := Vect.Vect.all (I); | |
54 | end loop; | |
55 | Delete (Vect.Vect); | |
56 | Vect.Vect := NRV_Access; | |
57 | Vect.Real_Length := New_Real_Length; | |
58 | end Expand; | |
59 | ||
60 | procedure Append (Vect : in out Vector; Tail : Component) is | |
61 | begin | |
62 | if Vect.Vect = null then | |
63 | Init (Vect); | |
64 | end if; | |
65 | if Vect.Length = Vect.Real_Length then | |
66 | Expand (Vect); | |
67 | end if; | |
68 | Vect.Vect.all (Vect.Length + 1) := Tail; | |
69 | Vect.Length := Index'Succ (Vect.Length); | |
70 | end Append; | |
71 | ||
72 | function Get (Vect : Vector; Pos : Index) return Component is | |
73 | begin | |
74 | if Debug and then (Pos > Vect.Length or else Pos = 0) then | |
75 | raise Bad_Position; | |
76 | end if; | |
77 | return Vect.Vect.all (Pos); | |
78 | end Get; | |
79 | ||
80 | procedure Set (Vect : in out Vector; Pos : in Index; Item : in Component) is | |
81 | begin | |
82 | if Debug and then Pos > Vect.Length then | |
83 | raise Bad_Position; | |
84 | end if; | |
85 | Vect.Vect.all (Pos) := Item; | |
86 | end Set; | |
87 | ||
88 | procedure Remove (Vect : in out Vector; Pos : in Index) is begin | |
89 | for I in Pos .. Vect.Length - 1 loop | |
90 | Set (Vect, I, Get (Vect, I + 1)); | |
91 | end loop; | |
92 | Vect.Length := Vect.Length - 1; | |
93 | end Remove; | |
94 | ||
95 | function Empty (Vect : Vector) return Boolean is begin | |
96 | return Vect.Length = 0; | |
97 | end Empty; | |
98 | ||
99 | function Length (Vect : Vector) return Index is begin | |
100 | return Vect.Length; | |
101 | end Length; | |
102 | ||
103 | function Advance (Old_Size : Natural) return Natural is | |
104 | begin | |
105 | if Old_Size < 250 then | |
106 | return 500; | |
107 | elsif Old_Size < 1_000_000 then | |
108 | return Old_Size * 2; | |
109 | else | |
110 | return Old_Size + 1_000_000; | |
111 | end if; | |
112 | end Advance; | |
113 | ||
114 | end Vector; |
0 | generic | |
1 | type Component is private; | |
2 | package Vector is | |
3 | ||
4 | subtype Index is Natural; | |
5 | ||
6 | type Vector is private; | |
7 | ||
8 | Bad_Position : exception; | |
9 | ||
10 | -- If the first operation is an append, then init is unnessecary. | |
11 | function New_Vector return Vector; | |
12 | procedure Init (New_Vect : out Vector); | |
13 | procedure Reinit (Vect : in out Vector); | |
14 | procedure Append (Vect : in out Vector; Tail : Component); | |
15 | procedure Expand (Vect : in out Vector; Times : Integer := 1); | |
16 | function Get (Vect : Vector; Pos : Index) return Component; | |
17 | procedure Set (Vect : in out Vector; Pos : in Index; Item : in Component); | |
18 | procedure Remove (Vect : in out Vector; Pos : in Index); | |
19 | function Length (Vect : Vector) return Index; | |
20 | function Empty (Vect : Vector) return Boolean; | |
21 | function Advance (Old_Size : Index) return Index; | |
22 | ||
23 | private | |
24 | ||
25 | pragma Inline (Append); | |
26 | pragma Inline (Expand); | |
27 | pragma Inline (Get); | |
28 | pragma Inline (Set); | |
29 | pragma Inline (Length); | |
30 | pragma Inline (Empty); | |
31 | ||
32 | type Real_Vector is array (Index range <>) of Component; | |
33 | ||
34 | type RV_Access is access Real_Vector; | |
35 | ||
36 | type Vector is record | |
37 | Length : Index; -- The index following the last one. | |
38 | Real_Length : Index; -- The actual length of the vector | |
39 | Vect : RV_Access; | |
40 | end record; | |
41 | ||
42 | end Vector; |