File: spacer.tcl

package info (click to toggle)
tcllib 1.20%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 68,064 kB
  • sloc: tcl: 216,842; ansic: 14,250; sh: 2,846; xml: 1,766; yacc: 1,145; pascal: 881; makefile: 107; perl: 84; f90: 84; python: 33; ruby: 13; php: 11
file content (151 lines) | stat: -rw-r--r-- 4,206 bytes parent folder | download | duplicates (7)
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
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2009 Andreas Kupries

# @@ Meta Begin
# Package tcl::transform::spacer 1
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2009
# Meta as::license BSD
# Meta description Implementation of a spacer
# Meta description transformation, using Tcl 8.6's
# Meta description transformation reflection support. Uses
# Meta description counters to implement the transformation,
# Meta description i.e. decide where to insert the spacing.
# Meta description Exports a single command adding a new
# Meta description transform of this type to a channel. One
# Meta description argument, the channel to extend. No
# Meta description result.
# Meta platform tcl
# Meta require tcl::transform::core
# Meta require {Tcl 8.6}
# @@ Meta End

# # ## ### ##### ######## #############

package require Tcl 8.6
package require tcl::transform::core

# # ## ### ##### ######## #############

namespace eval ::tcl::transform {}

proc ::tcl::transform::spacer {chan n {space { }}} {
    ::chan push $chan [spacer::implementation new $n $space]
    return
}

oo::class create ::tcl::transform::spacer::implementation {
    superclass tcl::transform::core ;# -> initialize, finalize, destructor

    # This transformation is intended for streaming operation. Seeking
    # the channel while it is active may cause undesirable
    # output. Proper behaviour may require the destruction of the
    # transform before seeking.

    method write {c data} {
	# add spacing, data is split into groups of delta chars.
	set result {}
	set len [string length $data]

	if {$woffset} {
	    # The beginning of the buffer is the remainder of the
	    # partial group found at the end of the buffer in the last
	    # call.  It may still be partial, if the current buffer is
	    # short enough.

	    if {($woffset + $len) < $delta} {
		# Yes, the group is still not fully covered.
		# Move the offset forward, and return the whole
		# buffer. spacing is not needed yet.
		incr woffset $len
		return $data
	    }

	    # The buffer completes the group. Add it and the following
	    # spacing, then fix the offset to start the processing of
	    # the groups coming after at the proper location.

	    set stop [expr {$delta - $woffset - 1}]

	    append result [string range $data 0 $stop]
	    append result $spacing

	    set  woffset $stop
	    incr woffset
	}

	# Process full groups in the middle of the incoming buffer.

	set at   $woffset
	set stop [expr {$at + $delta - 1}]
	while {$stop < $len} {
	    append result [string range $data $at $stop]
	    append result $spacing
	    incr at   $delta
	    incr stop $delta
	}

	# Process partial group at the end of the buffer and remember
	# the offset, for the processing of the group remainder in the
	# next call.

	if {($at < $len) && ($stop >= $len)} {
	    append result [string range $data $at end]
	}
	set woffset [expr {$len - $at}]
	return $result
    }

    method read {c data} {
	# remove spacing from groups of delta+sdelta chars, keeping
	# the first delta in each group.
	set result {}
	set iter [expr {$delta + $sdelta}]
	set at 0
	if {$roffset} {
	    if {$roffset < $delta} {
		append result [string range $data 0 ${roffset}-1]
	    }
	    incr at [expr {$iter - $roffset}]
	}
	set len  [string length $data]
	set end  [expr {$at + $delta - 1}]
	set stop [expr {$at + $iter - 1}]
	while {$stop < $len} {
	    append result [string range $data $at $end]
	    incr at   $iter
	    incr end  $iter
	    incr stop $iter
	}
	if {$end < $len} {
	    append result [string range $data $at $end]
	    set roffset [expr {$len - $end + 1}]
	} elseif {$at < $len} {
	    append result [string range $data $at end]
	    set roffset [expr {$len - $at}]
	}
	return [list $result $roffset]
    }

    # # ## ### ##### ######## #############

    constructor {n space} {
	set roffset 0
	set woffset 0
	set delta   $n
	set spacing $space
	set sdelta [string length $spacing]
	return
    }

    # # ## ### ##### ######## #############

    variable roffset woffset delta spacing sdelta

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## #############
package provide tcl::transform::spacer 1
return