home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Environments / Small Eiffel 0.4.8 / lib_std / std_file_read.e < prev    next >
Encoding:
Text File  |  1997-04-13  |  9.3 KB  |  425 lines  |  [TEXT/ttxt]

  1. -- Part of SmallEiffel -- Read DISCLAIMER file -- Copyright (C) 
  2. -- Dominique COLNET and Suzanne COLLIN -- colnet@loria.fr
  3. --
  4. class STD_FILE_READ 
  5. --
  6. -- Basic input facilities to read a named file on the disc.
  7. --
  8. -- Note : most features are common with STD_INPUT so you can 
  9. --        test your program on the screen first and then, just 
  10. --        changing of instance (STD_INPUT/STD_FILE_READ), doing 
  11. --        the same on a file.
  12. --
  13.    
  14. inherit STD_FILE
  15.    
  16. creation 
  17.    connect_to, make
  18.    
  19. feature 
  20.    
  21.    connect_to(new_path: STRING) is
  22.       do
  23.      make;
  24.      input_stream := fopen(new_path,mode);
  25.      if input_stream.is_not_void then
  26.         path := new_path;
  27.      end;
  28.       end;
  29.    
  30.    disconnect is
  31.       local
  32.      err: INTEGER;
  33.       do
  34.      err := fclose(input_stream); 
  35.      path := Void;
  36.       end;
  37.    
  38.    make is
  39.       do
  40.      mode := "r";
  41.       end;
  42.    
  43. feature    
  44.    
  45.    last_integer: INTEGER; 
  46.      -- Last integer read using `read_integer'.
  47.    
  48.    last_real: REAL; -- Last real read with `read_real'.
  49.    
  50.    last_double: DOUBLE; -- Last double read with `read_double'.
  51.    
  52.    last_character: CHARACTER is 
  53.      -- Last character read with `read_character'.
  54.       do 
  55.      Result := last_character_memory;
  56.       end;
  57.    
  58.    last_string: STRING is
  59.      -- Last STRING read with `read_line', `read_word' or `newline'.
  60.      --
  61.      -- NOTE: it is alway the same STRING.
  62.       once
  63.      !!Result.make(256);
  64.       end;
  65.    
  66.    read_line is
  67.      -- Read a complete line ended by '%N' or `end_of_input'. 
  68.      -- Make the result available in `last_string'.
  69.      -- Character '%N' is not added in `last_string'. 
  70.      --     
  71.      -- NOTE: the result is available in `last_string' without any 
  72.      --       memory allocation.
  73.       require
  74.      not end_of_input;
  75.       do
  76.      read_line_in(last_string);
  77.       end;
  78.          
  79.    read_line_in(str: STRING) is
  80.      -- Same jobs as `read_line' but storage is directly done in `str'.
  81.      --
  82.       require
  83.      not end_of_input;
  84.       do
  85.      from  
  86.         str.clear;
  87.         read_character;
  88.      until
  89.         end_of_input or else
  90.         last_character = '%N'
  91.      loop
  92.         str.extend(last_character);
  93.         read_character;
  94.      end;
  95.       end;
  96.          
  97.    read_word is
  98.      -- Read a word using `is_separator' of class CHARACTER. 
  99.      -- Result is available in `last_string' (no allocation 
  100.      -- of memory).
  101.      -- Heading separators are automatically skipped.
  102.      -- Trailing separators are not skipped (`last_character' is
  103.      -- left on the first one).  
  104.      -- If `end_of_input' is encountered, Result can be the 
  105.      -- empty string.
  106.       require
  107.      not end_of_input
  108.       do
  109.      skip_separators;
  110.      from  
  111.         last_string.clear;
  112.      until
  113.         end_of_input or else
  114.         last_character.is_separator
  115.      loop
  116.         last_string.extend(last_character);
  117.         read_character;
  118.      end;
  119.       end;
  120.    
  121.    read_word_using(separators: STRING) is
  122.      -- Same jobs as `read_word' using `separators'.
  123.       require 
  124.      not end_of_input;
  125.      separators /= void
  126.       do
  127.      -- Implemented by : Lars Brueckner 
  128.      -- (larsbruk@rbg.informatik.th-darmstadt.de)
  129.      skip_separators_using(separators);
  130.      from  
  131.         last_string.clear;
  132.      until
  133.         end_of_input or else
  134.         separators.has(last_character)
  135.      loop
  136.         last_string.extend(last_character);
  137.         read_character;
  138.      end;
  139.       end;
  140.     
  141.    read_integer is
  142.      -- Read an integer according to the Eiffel syntax.
  143.      -- Make result available in `last_integer'.
  144.      -- Heading separators (`is_separator' of CHARACTER)  
  145.      -- are automatically skipped.
  146.      -- Trailing sseparators are not skipped (`last_character'
  147.      -- is after the last digit of the number).
  148.       local
  149.      state: INTEGER;
  150.      sign: BOOLEAN;
  151.      -- state = 0 : waiting sign or first digit.
  152.      -- state = 1 : sign read, waiting first digit.
  153.      -- state = 2 : in the number.
  154.      -- state = 3 : end state.
  155.      -- state = 4 : error state.
  156.       do
  157.      from
  158.      until
  159.         state > 2
  160.      loop
  161.         read_character;
  162.         inspect 
  163.            state
  164.         when 0 then
  165.            if last_character.is_separator then
  166.            elseif last_character.is_digit then
  167.           last_integer := last_character.value;
  168.           state := 2;
  169.            elseif last_character = '-' then
  170.           sign := true;
  171.           state := 1;
  172.            elseif last_character = '+' then
  173.           state := 1;
  174.            else
  175.           state := 4;
  176.            end;
  177.         when 1 then
  178.            if last_character.is_separator then
  179.            elseif last_character.is_digit then
  180.           last_integer := last_character.value;
  181.           state := 2;
  182.            else
  183.           state := 4;
  184.            end;
  185.         else -- 2
  186.            if last_character.is_digit then
  187.           last_integer := (last_integer * 10) + last_character.value;
  188.            else
  189.           state := 3;
  190.            end;
  191.         end;
  192.      end;
  193.      debug
  194.         if state = 4 then
  195.            std_error.put_string("Error in STD_FILE_READ.read_integer.%N");
  196.            crash;
  197.         end;
  198.      end;
  199.      if sign then
  200.         last_integer := - last_integer;
  201.      end;
  202.       end;
  203.    
  204.    read_real is
  205.      -- Read a REAL and make the result available in `last_real'
  206.      -- and in `last_double'.
  207.      -- The integral part is available in `last_integer'.
  208.       do
  209.      read_double;
  210.      last_real := last_double.to_real;
  211.       end;
  212.    
  213.    read_double is
  214.      -- Read a DOUBLE and make the result available in 
  215.      -- `last_double'. 
  216.       local
  217.      state: INTEGER;
  218.      sign: BOOLEAN;
  219.      ip, i: INTEGER;
  220.      -- state = 0 : waiting sign or first digit.
  221.      -- state = 1 : sign read, waiting first digit.
  222.      -- state = 2 : in the integral part.
  223.          -- state = 3 : in the fractional part.
  224.      -- state = 4 : end state.
  225.      -- state = 5 : error state.
  226.       do
  227.      from
  228.      until
  229.         state >= 4
  230.      loop
  231.         read_character;
  232.         inspect 
  233.            state
  234.         when 0 then
  235.            if last_character.is_separator then
  236.            elseif last_character.is_digit then
  237.           ip := last_character.value;
  238.           state := 2;
  239.            elseif last_character = '-' then
  240.           sign := true;
  241.           state := 1;
  242.            elseif last_character = '+' then
  243.           state := 1;
  244.            elseif last_character = '.' then
  245.           tmp_read_double.clear;
  246.           state := 3;
  247.            else
  248.           state := 5;
  249.            end;
  250.         when 1 then
  251.            if last_character.is_separator then
  252.            elseif last_character.is_digit then
  253.           ip := last_character.value;
  254.           state := 2;
  255.            else
  256.           state := 5;
  257.            end;
  258.         when 2 then
  259.            if last_character.is_digit then
  260.           ip := (ip * 10) + last_character.value;
  261.            elseif last_character = '.' then
  262.           tmp_read_double.clear;
  263.           state := 3;
  264.            else
  265.           state := 4;
  266.            end;
  267.         else -- 3 
  268.            if last_character.is_digit then
  269.           tmp_read_double.extend(last_character);
  270.            else
  271.           state := 4;
  272.            end;
  273.         end;
  274.      end;
  275.      debug
  276.         if state = 5 then
  277.            std_error.put_string("Error in STD_FILE.read_double.%N");
  278.            crash;
  279.         end;
  280.      end;
  281.      from  
  282.         last_double := 0;
  283.         i := tmp_read_double.count;
  284.      until
  285.         i = 0
  286.      loop
  287.         last_double := (last_double + tmp_read_double.item(i).value) / 10;
  288.         i := i - 1;
  289.      end;
  290.      last_double := last_double + ip;
  291.      if sign then
  292.         last_double := - last_double;
  293.      end;
  294.       end;
  295.    
  296.    unread_character is
  297.      -- Un read the last character read.
  298.       local
  299.      err: INTEGER;
  300.       do
  301.      err := ungetc(last_character,input_stream);
  302.       end;
  303.    
  304.    read_character is
  305.      -- Read a character and assign it to `last_character'.
  306.       require
  307.      not end_of_input;
  308.       do
  309.      last_character_memory := fgetc(input_stream);
  310.       end;
  311.  
  312.    read_tail_in(str: STRING) is
  313.      -- Read all remaining character of the file in `str'.
  314.       do
  315.      from
  316.         if not end_of_input then
  317.            read_character;
  318.         end;
  319.      until
  320.         end_of_input
  321.      loop
  322.         str.extend(last_character);
  323.         read_character;
  324.      end;
  325.       ensure
  326.      end_of_input;
  327.       end;
  328.  
  329.    newline is
  330.      -- Consume input until newline is found.
  331.      -- Corresponding STRING is stored in `last_string'.
  332.      -- Then consume newline character.
  333.       do
  334.      from  
  335.         last_string.clear;
  336.      until
  337.         end_of_input or else last_character = '%N'
  338.      loop
  339.         read_character;
  340.         last_string.extend(last_character);
  341.      end;
  342.      if not end_of_input then
  343.         read_character;
  344.      end;      
  345.       end;
  346.       
  347.    end_of_input : BOOLEAN is
  348.      -- Has end-of-input been reached ?
  349.       do
  350.      Result := feof(input_stream)
  351.       end;
  352.  
  353. feature -- Skipping :
  354.  
  355.    skip_separators is
  356.      -- Stop doing `read_character' as soon as `end_of_file' is reached
  357.      -- or as soon as `last_character' is not `is_separator'.
  358.      -- When first character is already not `is_separator' nothing 
  359.      -- is done. 
  360.       do
  361.      from  
  362.      until
  363.         end_of_input or else 
  364.         not last_character.is_separator
  365.      loop
  366.         read_character;
  367.      end;
  368.       end;
  369.    
  370.    skip_separators_using(separators:STRING) is
  371.      -- Same job as `skip_separators' using `separators'.
  372.       require 
  373.      separators /= void;
  374.       do
  375.      -- Implemented by : Lars Brueckner 
  376.      -- (larsbruk@rbg.informatik.th-darmstadt.de)
  377.      from 
  378.      until
  379.         end_of_input or else 
  380.         not separators.has(last_character)
  381.      loop
  382.         read_character;
  383.      end;
  384.       end;
  385.   
  386. feature {FILE_TOOLS}
  387.  
  388.    same_as(other: like Current): BOOLEAN is
  389.       require
  390.      is_connected;
  391.      other.is_connected
  392.       local
  393.      is1, is2: like input_stream;
  394.       do
  395.      from
  396.         is1 := input_stream;
  397.         is2 := other.input_stream;
  398.         Result := true;
  399.      until
  400.         not Result or else feof(is1) 
  401.      loop
  402.         Result := fgetc(is1) = fgetc(is2);
  403.      end
  404.      disconnect;
  405.      other.disconnect;
  406.       ensure
  407.      not is_connected;
  408.      not other.is_connected
  409.       end;
  410.  
  411. feature {STD_FILE_READ}
  412.    
  413.    input_stream: POINTER;
  414.    
  415.    last_character_memory: CHARACTER;
  416.  
  417. feature {NONE}
  418.  
  419.    tmp_read_double: STRING is
  420.       once
  421.      !!Result.make(12);
  422.       end;
  423.  
  424. end -- STD_FILE_READ
  425.