Skip to content

Commit 03dfe48

Browse files
committed
Rename writer/newline to writer/endline to avoid conflict with clojure.core/newline
Add writef function to format values and then write Refactor write-binary out of format-binary Refactor write-binary-delta out of format-binary-delta Adjust binary-test for newline at end of each line (not as a separator)
1 parent 80c3322 commit 03dfe48

File tree

5 files changed

+86
-63
lines changed

5 files changed

+86
-63
lines changed

src/io/aviso/binary.clj

Lines changed: 71 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
(ns io.aviso.binary
22
"Utilities for formatting binary data (byte arrays) or binary deltas."
3-
(require [io.aviso.ansi :as ansi]
3+
(import (java.lang StringBuilder))
4+
(require [io.aviso
5+
[ansi :as ansi]
6+
[writer :as w]]
47
[clojure.string :as s]))
58

69
(defprotocol BinaryData
@@ -31,21 +34,19 @@
3134
(def ^:private ^:const bytes-per-diff-line 16)
3235
(def ^:private ^:const bytes-per-line (* 2 bytes-per-diff-line))
3336

34-
(defn- format-line
35-
[offset data line-count]
36-
(format
37-
"%04X:%s"
38-
offset
39-
(apply str
40-
(for [i (range line-count)]
41-
(format " %02X" (byte-at data (+ offset i)))))))
37+
(defn- write-line
38+
[writer offset data line-count]
39+
(w/writef writer "%04X:" offset)
40+
(doseq [i (range line-count)]
41+
(w/writef writer " %02X" (byte-at data (+ offset i))))
42+
(w/write writer w/endline))
4243

4344
(defn- join-lines
4445
"Joins all the lines together seperated by newlines."
4546
[lines]
4647
(s/join \newline lines))
4748

48-
(defn format-binary
49+
(defn write-binary
4950
"Formats a ByteData into a hex-dump string, consisting of multiple lines; each line formatted as:
5051
5152
0000: 4E 6F 77 20 69 73 20 74 68 65 20 74 69 6D 65 20 66 6F 72 20 61 6C 6C 20 67 6F 6F 64 20 6D 65 6E
@@ -55,16 +56,21 @@
5556
(32 bytes per line)
5657
5758
... that is, a four-byte offset, then up-to 32 bytes (depending on the length of the data)."
58-
[data]
59-
(loop [offset 0
60-
lines []]
61-
(let [remaining (- (data-length data) offset)]
62-
(if (< remaining 1)
63-
(join-lines lines)
64-
(recur (+ bytes-per-line offset)
65-
(conj lines
66-
(format-line offset data (min bytes-per-line remaining))))))))
59+
([data]
60+
(write-binary *out* data))
61+
([writer data]
62+
(loop [offset 0]
63+
(let [remaining (- (data-length data) offset)]
64+
(when (pos? remaining)
65+
(write-line writer offset data (min bytes-per-line remaining))
66+
(recur (+ bytes-per-line offset)))))))
6767

68+
(defn format-binary
69+
"Formats the data as with write-binary and returns the result as a string."
70+
[data]
71+
(let [result (StringBuilder. (* 3 (data-length data)))]
72+
(write-binary result data)
73+
(.toString result)))
6874

6975
(defn- match?
7076
[byte-offset data-length data alternate-length alternate]
@@ -75,35 +81,53 @@
7581

7682
(defn- to-hex
7783
[byte-array byte-offset]
84+
;; This could be made a lot more efficient!
7885
(format "%02X" (byte-at byte-array byte-offset)))
7986

80-
81-
(defn- format-byte-deltas
82-
[ansi-color pad? offset data-length data alternate-length alternate]
83-
(apply str
84-
(for [i (range bytes-per-diff-line)]
85-
(let [byte-offset (+ offset i)]
86-
(cond
87-
;; Exact match on both sides is easy, just print it out.
88-
(match? byte-offset data-length data alternate-length alternate) (str " " (to-hex data byte-offset))
89-
;; Some kind of mismatch, so decorate with this side's color
90-
(< byte-offset data-length) (str " " (ansi-color (to-hex data byte-offset)))
91-
;; Are we out of data on this side? Print a "--" decorated with the color.
92-
(< byte-offset alternate-length) (str " " (ansi-color "--"))
93-
;; This side must be longer than the alternate side.
94-
;; On the left/green side, we need to pad with spaces
95-
pad? " "
96-
;; On the right/red side, we need nothing.
97-
:else "")))))
98-
99-
(defn- format-delta-line
100-
[offset expected-length ^bytes expected actual-length actual]
87+
(defn- write-byte-deltas
88+
[writer ansi-color pad? offset data-length data alternate-length alternate]
89+
(doseq [i (range bytes-per-diff-line)]
90+
(let [byte-offset (+ offset i)]
91+
(cond
92+
;; Exact match on both sides is easy, just print it out.
93+
(match? byte-offset data-length data alternate-length alternate) (w/writes writer " " (to-hex data byte-offset))
94+
;; Some kind of mismatch, so decorate with this side's color
95+
(< byte-offset data-length) (w/writes writer " " (ansi-color (to-hex data byte-offset)))
96+
;; Are we out of data on this side? Print a "--" decorated with the color.
97+
(< byte-offset alternate-length) (w/writes writer " " (ansi-color "--"))
98+
;; This side must be longer than the alternate side.
99+
;; On the left/green side, we need to pad with spaces
100+
;; On the right/red side, we need nothing.
101+
pad? (w/write writer " ")))))
102+
103+
(defn- write-delta-line
104+
[writer offset expected-length ^bytes expected actual-length actual]
101105
(let [line-count (max (min bytes-per-diff-line (- expected-length offset))
102106
(min bytes-per-diff-line (- actual-length offset)))]
103-
(format "%04X:%s |%s"
104-
offset
105-
(format-byte-deltas ansi/bold-green true offset expected-length expected actual-length actual)
106-
(format-byte-deltas ansi/bold-red false offset actual-length actual expected-length expected))))
107+
(w/writef writer "%04X:" offset)
108+
(write-byte-deltas writer ansi/bold-green true offset expected-length expected actual-length actual)
109+
(write-byte-deltas writer ansi/bold-red false offset actual-length actual expected-length expected)
110+
(w/write writer w/endline)))
111+
112+
(defn write-binary-delta
113+
"Formats a hex dump of the expected data (on the left) and actual data (on the right). Bytes
114+
that do not match are highlighted in green on the expected side, and red on the actual side.
115+
When one side is shorter than the other, it is padded with -- placeholders to make this
116+
more clearly visible.
117+
118+
expected - ByteData
119+
actual - ByteData
120+
121+
Display 16 bytes (from each data set) per line."
122+
([expected actual] (write-binary-delta *out* expected actual))
123+
([writer expected actual]
124+
(let [expected-length (data-length expected)
125+
actual-length (data-length actual)
126+
target-length (max actual-length expected-length)]
127+
(loop [offset 0]
128+
(when (pos? (- target-length offset))
129+
(write-delta-line writer offset expected-length expected actual-length actual)
130+
(recur (+ bytes-per-diff-line offset)))))))
107131

108132
(defn format-binary-delta
109133
"Formats a hex dump of the expected data (on the left) and actual data (on the right). Bytes
@@ -116,13 +140,6 @@
116140
117141
Display 16 bytes (from each data set) per line."
118142
[expected actual]
119-
(let [expected-length (data-length expected)
120-
actual-length (data-length actual)
121-
target-length (max actual-length expected-length)]
122-
(loop [offset 0
123-
lines []]
124-
(if (< (- target-length offset) 1)
125-
(join-lines lines)
126-
(recur (+ bytes-per-diff-line offset)
127-
(conj lines
128-
(format-delta-line offset expected-length expected actual-length actual)))))))
143+
(let [result (StringBuilder. 2000)]
144+
(write-binary-delta result expected actual)
145+
(.toString result)))

src/io/aviso/exception.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@
194194
(justify line-width line)
195195
(w/write " ")
196196
(justify class-width class)
197-
(w/writes "." method w/newline)))))
197+
(w/writes "." method w/endline)))))
198198

199199

200200
(defn write-exception
@@ -220,7 +220,7 @@
220220
(if message
221221
(str " " message-font message reset-font)
222222
"")
223-
w/newline)
223+
w/endline)
224224

225225
(let [properties (update-keys (:properties e) name)
226226
prop-keys (keys properties)
@@ -231,7 +231,7 @@
231231
(max-length prop-keys))]
232232
(doseq [k (sort prop-keys)]
233233
(justify writer prop-name-width property-font k reset-font)
234-
(w/writes writer ": " (get properties k) w/newline))
234+
(w/writes writer ": " (get properties k) w/endline))
235235
(if (:root e)
236236
(write-stack-trace writer exception))))))))
237237

src/io/aviso/writer.clj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
[writer & values]
1919
(write writer (apply str values)))
2020

21-
(def newline
21+
(defn writef
22+
"Writes formatted data."
23+
[writer fmt & values]
24+
(write writer (apply format fmt values)))
25+
26+
(def endline
2227
"End-of-line terminator, platform specific."
2328
(System/getProperty "line.separator"))
2429

test/io/aviso/binary_test.clj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111
(are [input output]
1212
(= (format-string-as-byte-array input) output)
1313

14-
"Hello" "0000: 48 65 6C 6C 6F"
14+
"Hello" "0000: 48 65 6C 6C 6F\n"
1515
"This is a longer text that spans to a second line."
16-
"0000: 54 68 69 73 20 69 73 20 61 20 6C 6F 6E 67 65 72 20 74 65 78 74 20 74 68 61 74 20 73 70 61 6E 73\n0020: 20 74 6F 20 61 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E"))
16+
"0000: 54 68 69 73 20 69 73 20 61 20 6C 6F 6E 67 65 72 20 74 65 78 74 20 74 68 61 74 20 73 70 61 6E 73\n0020: 20 74 6F 20 61 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E\n"))
1717

1818
(deftest format-string-as-byte-data
1919
(are [input output]
2020
(= (format-binary input) output)
2121
"" ""
22-
"Hello" "0000: 48 65 6C 6C 6F"
22+
"Hello" "0000: 48 65 6C 6C 6F\n"
2323
"This is a longer text that spans to a second line."
24-
"0000: 54 68 69 73 20 69 73 20 61 20 6C 6F 6E 67 65 72 20 74 65 78 74 20 74 68 61 74 20 73 70 61 6E 73\n0020: 20 74 6F 20 61 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E"))
24+
"0000: 54 68 69 73 20 69 73 20 61 20 6C 6F 6E 67 65 72 20 74 65 78 74 20 74 68 61 74 20 73 70 61 6E 73\n0020: 20 74 6F 20 61 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E\n"))
2525

2626
(deftest nil-is-an-empty-data
2727
(is (= (format-binary nil) "")))

test/user.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns user
22
(import (java.sql SQLException))
3-
(use [io.aviso ansi binary exception]))
3+
(use [io.aviso ansi binary exception]
4+
[clojure test]))
45

56
(defn make-exception
67
"Creates a sample exception used to test the exception formatting logic."

0 commit comments

Comments
 (0)