rsfile_1.0.1_f3d68468/src/rsfile.adb

  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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
with Ada.Command_Line;
with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Directories;
with Ada.Exceptions;
with Ada.Numerics.Discrete_Random;
with Ada.Strings.Unbounded; 	use Ada.Strings.Unbounded;
with Ada.Text_IO;

with Gnat.OS_Lib;
with GNAT.Traceback.Symbolic;

procedure Rsfile is

   Exit_OK  : constant := 0;
   Exit_Arg : constant := 1;
   Exit_Ex  : constant := 2;

   function "+" (S : String) return Unbounded_String
                 renames To_Unbounded_String;

   --  procedure Log (S : String) renames Ada.Text_IO.Put_Line;
   procedure Log (S : String) is null;

   use type Ada.Directories.File_Size;
   package Size_File is new Ada.Containers.Indefinite_Ordered_Maps
     (Ada.Directories.File_Size, String);

   Root : Unbounded_String;

   Candidates : Size_File.Map;

   -----------------
   -- Print_Usage --
   -----------------

   procedure Print_Usage is
      use Ada.Command_Line;
      use Ada.Text_IO;
   begin
      Put_Line ("Usage: " & Ada.Directories.Simple_Name (Command_Name) & " <path>");
   end Print_Usage;

   ----------------------
   -- Check_Parameters --
   ----------------------

   function Check_Parameters return Boolean is
     use Ada.Command_Line;
   begin
      if Argument_Count /= 1 then
         Print_Usage;
         return False;
      else
         Root := +Argument (1);
         return True;
      end if;
   end Check_Parameters;

   -------------------
   -- Populate_Tree --
   -------------------

   procedure Populate_Tree is
      use Ada.Directories;
      Root : String := To_String (Rsfile.Root);
      Pos  : File_Size := 0;

      ----------------------
      -- Enumerate_Folder --
      ----------------------

      procedure Enumerate_Folder (Folder : String) is
         St   : Search_Type;
      begin
         Log ("Entering: " & Folder);
         Start_Search (St, Folder, "");

         while More_Entries (St) loop
            declare
               Item : Directory_Entry_Type;
            begin
               Get_Next_Entry (St, Item);

               case Kind (Item) is
                  when Directory =>
                     if
                       Simple_Name (Item) /= "." and then
                       Simple_Name (Item) /= ".."
                     then
                        Enumerate_Folder (Full_Name (Item));
                     end if;
                  when Ordinary_File =>
                     Pos := Pos + Size (Item) + 1;
                     Log ("Insert: " & Simple_Name (Item) & " at" & Pos'Img);
                     Candidates.Insert (Pos, Full_Name (Item));
                  when others =>
                     Log ("Skipping: " & Simple_Name (Item));
               end case;
            end;
         end loop;
      exception
         when others =>
           End_Search (St);
         raise;
      end Enumerate_Folder;

   begin
      Enumerate_Folder (Root);
   end Populate_Tree;

   ---------------
   -- Pick_File --
   ---------------

   procedure Pick_File is
      use Ada.Directories;
      subtype Targets is File_Size range 0 .. Candidates.Last_Key;
      package FSRnd is new Ada.Numerics.Discrete_Random (Targets);
      Rnd : FSRnd.Generator;
   begin
      FSRnd.Reset (Rnd);

      declare
         Index  : constant File_Size := FSRnd.Random (Rnd);

         Target : constant String :=
           Size_File.Element
             (Candidates.Ceiling
                  (Index));
      begin
         Ada.Text_IO.Put_Line (Target);
      end;
   end Pick_File;

   use Gnat.OS_Lib;

begin
   if not Check_Parameters then
      Os_Exit(Exit_Arg);
   end if;

   Populate_Tree;

   Pick_File;

   Os_Exit (Exit_OK);
exception
   when E : others =>
      declare
         use Ada.Exceptions;
         use Ada.Text_IO;
      begin
         Put_Line ("Couldn't complete:");
         Put_Line ("Exception:   " & Exception_Message (E));
         Put_Line ("Information: " & Exception_Information (E));
         Put_Line ("Call stack:  " & Gnat.Traceback.Symbolic.Symbolic_Traceback (E));
         Os_Exit (Exit_Ex);
      end;
end Rsfile;