From: mfb@mbunix.mitre.org (Michael F Brenner)
Subject: Re: Parsing a line into strings
Date: 1998/07/09
Date: 1998-07-09T00:00:00+00:00 [thread overview]
Message-ID: <6o2jjm$e9@top.mitre.org> (raw)
In-Reply-To: dewar.899956473@merv
Some code was posted to this list last year which might do some of the
functionality you wish (depending on what that functionality is).
EXTRACT FROM THIS NEWSGROUP FROM LAST YEAR:
----------------------------------------------------------------------
package fielder is
pragma pure (fielder);
-- Sets left_field and right_field to the column pointers dividing
-- BUFFER into fields.
--
-- The field boundaries are any noticed characters (currently eoln & blank)
-- Computes the number_of_fields. Field zero means the entire buffer
-- (all fields).
--
-- Suggested usage:
--
-- procedure try_fielder is
-- fielding: fieldings;
-- message: string (1..80);
-- message_length: natural := 49; -- the characters used in MESSAGE
-- begin
-- break_into_fields (message, message_length, fielding);
-- print ("field (1)=" &
-- message (fielding.left_field(1) .. fielding.right_field(1));
-- end try_fielder;
--
type field_lists is array (0..255) of natural;
type fieldings is record
left_field, right_field: field_lists;
number_of_fields: natural;
end record;
procedure break_into_fields (buffer: string;
length: natural;
fielding: in out fieldings;
blank1: character := ' ';
blank2: character := ascii.ht);
-- After break_into_fields, fielding contains
-- the left and right boundaries of each
-- of the fields. Used for efficient access
-- to those boundaries in the long form of
-- field.
function field (field_no: natural;
buffer: string;
length: natural;
fielding: fieldings) return string;
-- The long form of FIELD returns the
-- desired field as broken up in FIELDING.
-- This breaks is up once and returns
-- many fields without breaking it up again.
function field (field_no: natural;
buffer: string) return string;
-- The short form of FIELD returns the
-- desired field, breaking the buffer up
-- into fields each time it is called.
-- Good for one-time calls, but bad for loops.
procedure nullify (field_no: natural;
buffer: in out string; -- length doesnt change
length: in out natural;
fielding: in out fieldings);
-- After NULLIFY, the desired field is
-- all blanks and fielding reflects that
procedure set_field (field_no: natural; -- field to be replaced
buffer: in out string; -- length doesnt change
length: in out natural; -- changes
fielding: in out fieldings; -- changes
new_data: string); -- is inserted
end fielder;
package body fielder is
procedure break_into_fields (buffer: string;
length: natural;
fielding: in out fieldings;
blank1: character := ' ';
blank2: character := ascii.ht) is
-- After the procedure BREAK_INTO_FIELDS is called, the FIELDING
-- contains updated LEFT AND RIGHT. LEFT(1) points to the leftmost
-- character in the first field. FIELD(1) returns the first field.
-- FIELD(0) returns buffer (1..length). Nullify sets a field to
-- null, shifting the other arguments down a position, like $2="" in awk.
end_of_line_character: constant character := character'val (10);
type bit_lists is array (character) of boolean;
pragma pack (bit_lists);
noticed: bit_lists := (others => false);
column_upto: natural := buffer'first;
ch: character := ' ';
fielder_len_gt_length: exception;
last: constant natural := buffer'first - 1 + length;
procedure get_next_character is
begin
if column_upto > last then
ch := end_of_line_character;
else
ch := buffer (column_upto);
end if;
column_upto := column_upto + 1;
end get_next_character;
procedure find_a_non_blank is
begin
loop
get_next_character;
exit when not noticed (ch);
exit when ch = end_of_line_character;
end loop;
end find_a_non_blank;
begin
noticed (end_of_line_character) := true;
noticed (blank1) := true;
noticed (blank2) := true;
fielding.number_of_fields := 0;
for j in 1..fielding.left_field'last loop
fielding.left_field(j) := 0;
fielding.right_field(j) := 0;
end loop; -- Permits user to ask for field 2 when there is only 1 field.
fielding.left_field (0) := buffer'first;
fielding.right_field(0) := last;
if length>buffer'length then
raise fielder_len_gt_length;
end if;
loop
find_a_non_blank;
exit when ch = end_of_line_character;
fielding.number_of_fields := fielding.number_of_fields+1;
fielding.left_field(fielding.number_of_fields) := column_upto-1;
if fielding.number_of_fields = field_lists'last then
fielding.right_field (fielding.number_of_fields) := buffer'last;
exit;
end if;
loop
get_next_character;
exit when noticed (ch);
end loop;
fielding.right_field(fielding.number_of_fields) := column_upto - 2;
exit when ch = end_of_line_character;
end loop;
end break_into_fields;
function field (field_no: natural;
buffer: string;
length: natural;
fielding: fieldings) return string is
lf: natural renames fielding.left_field (field_no);
rf: natural renames fielding.right_field (field_no);
n: natural renames fielding.number_of_fields;
begin
if field_no = 0 then
return buffer (1..length);
elsif length = 0 or else field_no > N or else rf < lf then
return "";
else
declare
subtype desired_columns is natural range LF .. RF;
size: constant integer := RF + 1 - LF;
alternate_buffer: constant string (1..size) := buffer (desired_columns);
begin
return alternate_buffer;
end;
end if;
end field;
function field (field_no: natural;
buffer: string) return string is
fielding: fieldings;
aligned_buffer: constant string (1..buffer'length) := buffer;
begin
break_into_fields (aligned_buffer, buffer'length, fielding);
return field (field_no, aligned_buffer, buffer'length, fielding);
end field;
procedure nullify (field_no: natural;
buffer: in out string; -- length not changed
length: in out natural;
fielding: in out fieldings) is
-- NULLIFY removes a field, shifting all the other fields left one field.
-- If the fields were (1=> "AA", 2=> "BC", 3=> "ZZ"), then after giving
-- NULLIFY (2), the fields are (1=> "AA", 2=> "ZZ"). Nullify(0) nullfies
-- all fields.
begin
if field_no=0 then
fielding.left_field(0) := 0;
fielding.right_field(0) := 0;
fielding.number_of_fields := 0;
for c in buffer'range loop
buffer (c) := ' ';
end loop;
buffer(buffer'first) := ascii.nul;
-- All fields will be nullified by the loop below.
elsif field_no > fielding.number_of_fields then
null;
-- Nothing is changed by the loop below.
elsif fielding.number_of_fields > 0 then
for c in fielding.left_field(field_no)..
fielding.right_field(field_no) loop
buffer(c) := ' ';
end loop;
for j in field_no..fielding.number_of_fields - 1 loop
fielding.left_field(j) := fielding.left_field(j+1);
fielding.right_field(j) := fielding.right_field(j+1);
end loop;
fielding.number_of_fields := fielding.number_of_fields - 1;
-- One field is nullified by the loop below;
end if;
for j in fielding.number_of_fields+1 ..
fielding.left_field'last loop
fielding.left_field(j) := 0;
fielding.right_field(j) := 0;
end loop;
length := fielding.right_field (fielding.number_of_fields);
-- Unused fields are set to zero length
end nullify;
procedure set_field (field_no: natural; -- field to be replaced
buffer: in out string; -- length does not change
length: in out natural; -- changes
fielding: in out fieldings; -- changes
new_data: string) is -- is inserted
-- The message is broken into three parts: A B C:
-- @ A contains the fields to the left of field (field_no)
-- @ B contains the new field (field_no) which MAY CONTAIN BLANKS
-- @ C contains the fields to the right of field (field_no)
A: constant string := buffer(1..fielding.left_field(field_no)-1);
B: string renames new_data;
C: constant string := buffer(fielding.right_field(field_no)+1..length);
set_field_too_long: exception;
procedure set_buffer (message: string) is
begin
if message'length > buffer'length then
raise set_field_too_long;
end if;
buffer (1..message'length) := message;
for i in natural(message'length+1)..buffer'length loop
buffer (i) := ' ';
end loop;
length := message'length;
end set_buffer;
begin
if A'length=0 and C'length=0 then
set_buffer (B);
elsif A'length=0 then
set_buffer (B & ' ' & C);
elsif B'length=0 then
set_buffer (A & ' ' & B);
else
set_buffer (A & ' ' & B & ' ' & C);
end if;
break_into_fields (buffer, length, fielding);
end set_field;
end fielder;
with fielder;
procedure ttfield is
x: constant string := " abc def ghi";
L: natural := x'length;
y: string (1..12) := (others => 'A');
yl: natural := 0;
tsfield_1: exception;
tsfield_2: exception;
use fielder;
fielding: fieldings;
procedure assert(condition: boolean) is
ttfield_failed: exception;
begin
if not condition then
raise ttfield_failed;
end if;
end assert;
begin
break_into_fields (x, L, fielding);
if fielding.number_of_fields /= 3 or else
field (1, x, L, fielding) /= "abc" or else
field (2, x, L, fielding) /= "def" or else
field (3, x, L, fielding) /= "ghi" then
raise tsfield_1;
end if;
if fielder.key ("a b c", 3, 1) /= "c~a" then
raise tsfield_2;
end if;
fielder.break_into_fields (y, yl, fielding);
fielder.set_field (0, y, yl, fielding, "");
assert(yl=0);
y(1..5):= "a b c";
yl:=5;
fielder.break_into_fields (y, yl, fielding);
assert(yl=5);
fielder.set_field (0, y, yl, fielding, "");
assert(yl=0);
end ttfield;
-------------------------------------------------------
next prev parent reply other threads:[~1998-07-09 0:00 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
1998-07-08 0:00 Parsing a line into strings C N
1998-07-08 0:00 ` Samuel Tardieu
1998-07-08 0:00 ` C N
1998-07-09 0:00 ` Dmitriy Anisimkov
1998-07-08 0:00 ` Brian Rogoff
1998-07-08 0:00 ` Robert Dewar
1998-07-09 0:00 ` Brian Rogoff
1998-07-08 0:00 ` nabbasi
1998-07-09 0:00 ` Robert Dewar
1998-07-09 0:00 ` Michael F Brenner [this message]
1998-07-14 0:00 ` Norman H. Cohen
1998-07-15 0:00 ` Robert I. Eachus
1998-07-18 0:00 ` Robert Dewar
1998-07-09 0:00 ` Dale Stanbrough
1998-07-09 0:00 ` dennison
1998-07-09 0:00 ` Darren Davenport
1998-07-10 0:00 ` Robert I. Eachus
1998-07-11 0:00 ` david.c.hoos.sr
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox