home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_std / input_stream.e < prev    next >
Text File  |  1999-06-05  |  12KB  |  427 lines

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