logo       
Google Custom Search
    AddThis Social Bookmark Button

r10279 - trunk/src/common/stream-ext: msg#00062

Subject: r10279 - trunk/src/common/stream-ext
Author: housel
Date: Wed Oct 19 23:50:36 2005
New Revision: 10279

Modified:
   trunk/src/common/stream-ext/indenting-streams.dylan
Log:
Bug: 7099 7266
Re-implement <indenting-stream> to improve its efficiency and correctness.

* indenting-streams.dylan
  (<indenting-stream>): Add new input-tab-width: and output-tab-width: keywords
  for controlling the tab width of the input and output to the wrapper stream.
  An output-tab-width: value of #f disables the use of tabs on output.
  (write-indent): New function for efficiently writing indenting spaces.
  (write-element): Re-implement to properly keep track of the current
  indentation space column and to use write-indent.
  (write): Re-implement to properly keep track of the current indentation
  space column, and to make a minimum number of calls to write() on the
  inner stream.


Modified: trunk/src/common/stream-ext/indenting-streams.dylan
==============================================================================
--- trunk/src/common/stream-ext/indenting-streams.dylan (original)
+++ trunk/src/common/stream-ext/indenting-streams.dylan Wed Oct 19 23:50:36 2005
@@ -1,10 +1,10 @@
 module: indenting-streams
-author: William Lott
+author: William Lott, Peter S. Housel
 
 //======================================================================
 //
 // Copyright (c) 1996  Carnegie Mellon University
-// Copyright (c) 1998, 1999, 2000  Gwydion Dylan Maintainers
+// Copyright (c) 1998, 1999, 2000, 2004, 2005  Gwydion Dylan Maintainers
 // All rights reserved.
 // 
 // Use and copying of this software and preparation of derivative
@@ -44,62 +44,138 @@
 
 
 define sealed class <indenting-stream> (<wrapper-stream>)
-  slot is-after-newline? :: <boolean> = #t;
-  slot is-column :: <integer> = 0;
+  slot is-space-column :: false-or(<integer>) = 0;
   slot is-indentation :: <integer> = 0, init-keyword: indentation:;
+  slot is-input-tab-width :: <integer> = 8, init-keyword: input-tab-width:;
+  slot is-output-tab-width :: false-or(<integer>) = 8,
+    init-keyword: output-tab-width:;
 end;
 
 define sealed domain make(singleton(<indenting-stream>));
 define sealed domain initialize(<indenting-stream>);
 
-define method write-element
-    (stream :: <indenting-stream>, elt :: <character>) => ()
-  if (stream.is-after-newline?)
-    for (i from 0 below stream.is-indentation)
-      write-element(stream.inner-stream, ' ');
-    end;
-    stream.is-after-newline? := #f;
-  end if;
-  write-element(stream.inner-stream, elt);
-  if (elt == '\t')
-    stream.is-column := stream.is-column + 8 - truncate/(stream.is-column, 8);
+define constant $spaces :: <byte-string>
+  = "                                                                "; // 64
+define constant $tabs :: <byte-string>
+  = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; // 32
+
+define function write-indent
+    (istream :: <indenting-stream>, count :: <integer>)
+ => ();
+  let stream = istream.inner-stream;
+  
+  local
+    method write-spaces (count :: <integer>) => ();
+      if (count > size($spaces))
+        write(stream, $spaces);
+        write-spaces(count - size($spaces));
+      else
+        write(stream, $spaces, end: count);
+      end if;
+    end,
+    method write-tabs (count :: <integer>) => ();
+      if (count > size($tabs))
+        write(stream, $tabs);
+        write-tabs(count - size($tabs));
+      else
+        write(stream, $tabs, end: count);
+      end if;
+    end method;
+
+  let tab-width = istream.is-output-tab-width;
+  if (tab-width & tab-width >= count)
+    let (tabs, spaces) = truncate/(count, tab-width);
+    write-tabs(tabs);
+    write-spaces(spaces);
   else
-    stream.is-column := stream.is-column + 1;
-  end;
+    write-spaces(count);
+  end if;
+end function;
+
+define method write-element
+    (stream :: <indenting-stream>, elt :: <character>)
+ => ()
+  select(elt)
+    ' ' =>
+      if (stream.is-space-column)
+        stream.is-space-column := stream.is-space-column + 1;
+      else
+        write-element(stream.inner-stream, elt);
+      end if;
+    '\t' =>
+      if (stream.is-space-column)
+        let tab-width = stream.is-input-tab-width;
+        stream.is-space-column
+          := stream.is-space-column
+          + tab-width
+          - remainder(stream.is-space-column, tab-width);
+      else
+        write-element(stream.inner-stream, elt);
+      end if;
+    '\n', '\r' =>
+      stream.is-space-column := 0;
+      write-element(stream.inner-stream, elt);
+    otherwise =>
+      if (stream.is-space-column)
+        write-indent(stream, stream.is-indentation + stream.is-space-column);
+      end if;
+      stream.is-space-column := #f;
+      write-element(stream.inner-stream, elt);
+  end select;
 end method write-element;
 
 define method write
     (stream :: <indenting-stream>, elements :: <sequence>,
-     #key start: _start = 0, end: _end = elements.size) => ()
-  if (stream.is-after-newline?)
-    for (i from 0 below stream.is-indentation)
-      write-element(stream.inner-stream, ' ');
-    end;
-    stream.is-after-newline? := #f;
-  end if;
-  write(stream.inner-stream, elements, start: _start, end: _end);
-  for (i from _start below _end,
-       col = stream.is-column
-         then if (elements[i] = '\t')
-                col + 8 - truncate/(col, 8)
-              else
-                col + 1
-              end)
-  finally
-    stream.is-column := col;
-  end;
+     #key start: _start = 0, end: _end = elements.size)
+ => ();
+  let inner = stream.inner-stream;
+  let tab-width = stream.is-input-tab-width;
+
+  iterate loop (index :: <integer> = _start,
+                start :: <integer> = _start,
+                space-column :: false-or(<integer>) = stream.is-space-column)
+    if (index < _end)
+      let elt = elements[index];
+      select (elt)
+        ' ' =>
+          if (space-column)
+            loop(index + 1, index + 1, space-column + 1);
+          else
+            loop(index + 1, start, #f);
+          end if;
+        '\t' =>
+          if (space-column)
+            loop(index + 1, index + 1,
+                 space-column + tab-width - remainder(space-column, 
tab-width));
+          else
+            loop(index + 1, start, #f);
+          end if;
+        '\n', '\r' =>
+          write(inner, elements, start: start, end: index + 1);
+          loop(index + 1, index + 1, 0);
+        otherwise =>
+          if (space-column)
+            write-indent(stream, stream.is-indentation + space-column);
+          end if;
+          loop(index + 1, start, #f);
+      end select;
+    else
+      if (start ~= index)
+        write(inner, elements, start: start, end: index);
+      end if;
+      stream.is-space-column := space-column;
+    end if;
+  end iterate;
 end method write;
 
 define method new-line (stream :: <indenting-stream>) => ()
-  stream.is-after-newline? := #t;
-  stream.is-column := 0;
+  stream.is-space-column := 0;
   new-line(stream.inner-stream)
 end method new-line;
 
 define method discard-output
     (stream :: <indenting-stream>) => ()
-  stream.is-after-newline? := #t;
-  stream.is-column := 0;
+  stream.is-space-column := 0;
   discard-output(stream.inner-stream)
 end method discard-output;
 
-- 
Gd-chatter mailing list
Gd-chatter@xxxxxxxxxxxxxxxx
https://gauss.gwydiondylan.org/mailman/listinfo/gd-chatter




Try Searching:
servers, voip, java, networking, microsoft ...
<Prev in Thread] Current Thread [Next in Thread>