• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rokath / trice / 20314806283

17 Dec 2025 07:12PM UTC coverage: 46.561% (-9.6%) from 56.117%
20314806283

push

github

rokath
minor corrections

2532 of 5438 relevant lines covered (46.56%)

868.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.5
/internal/trexDecoder/trexDecoder.go
1
// Copyright 2022 Thomas.Hoehenleitner [at] seerose.net
2
// Use of this source code is governed by a license that can be found in the LICENSE file.
3

4
package trexDecoder
5

6
import (
7
        "bytes"
8
        "encoding/binary"
9
        "encoding/hex"
10
        "fmt"
11
        "io"
12
        "log"
13
        "math"
14
        "strings"
15
        "sync"
16

17
        cobs "github.com/rokath/cobs/go"
18
        "github.com/rokath/tcobs/v1"
19
        "github.com/rokath/trice/internal/decoder"
20
        "github.com/rokath/trice/internal/emitter"
21
        "github.com/rokath/trice/internal/id"
22
        "github.com/rokath/trice/pkg/cipher"
23
)
24

25
const (
26
        tyIdSize = 2 // tySize is what each trice message starts with: 2 bytes
27
        ncSize   = 2 // countSize is what each regular trice message contains after an optional target timestamp
28
        typeS0   = 1 // regular trice format without stamp     : 011iiiiiI NC ...
29
        typeS2   = 2 // regular trice format with 16-bit stamp : 101iiiiiI TT NC ...
30
        typeS4   = 3 // regular trice format with 32-bit stamp : 111iiiiiI TT TT NC ...
31
        typeX0   = 0 // regular trice format with 32-bit stamp : 001iiiiiI TT TT TT TT NC ...
32

33
        packageFramingNone = iota
34
        packageFramingCOBS
35
        packageFramingTCOBS   //v1
36
        packageFramingTCOBSv2 //v2
37
)
38

39
var (
40
        Doubled16BitID               bool
41
        AddNewlineToEachTriceMessage bool
42
        SingleFraming                bool // SingleFraming demands, that each received package contains not more than a singe Trice message.
43
        DisableCycleErrors           bool
44
)
45

46
// trexDec is the Decoding instance for trex encoded trices.
47
type trexDec struct {
48
        decoder.DecoderData
49
        cycle          uint8  // cycle date: c0...bf
50
        pFmt           string // modified trice format string: %u -> %d
51
        u              []int  // 1: modified format string positions:  %u -> %d, 2: float (%f)
52
        packageFraming int
53
}
54

55
// New provides a TREX decoder instance.
56
//
57
// l is the trice id list in slice of struct format.
58
// in is the usable reader for the input bytes.
59
func New(w io.Writer, lut id.TriceIDLookUp, m *sync.RWMutex, li id.TriceIDLookUpLI, in io.Reader, endian bool) decoder.Decoder {
1✔
60
        // Todo: rewrite using the TCOBS Reader. The provided in io.Reader provides a raw data stream.
1✔
61
        // https://github.com/rokath/tcobs/blob/master/TCOBSv1/read.go -> use NewDecoder ...
1✔
62

1✔
63
        p := &trexDec{}
1✔
64
        p.cycle = 0xc0 // start value
1✔
65
        p.W = w
1✔
66
        p.In = in
1✔
67
        p.IBuf = make([]byte, 0, decoder.DefaultSize)     // len 0
1✔
68
        p.B = make([]byte, 0, decoder.DefaultSize)        // len 0
1✔
69
        p.B0 = make([]byte, decoder.DefaultSize)          // len max
1✔
70
        p.InnerBuffer = make([]byte, decoder.DefaultSize) // len max
1✔
71
        p.Lut = lut
1✔
72
        p.LutMutex = m
1✔
73
        p.Endian = endian
1✔
74
        p.Li = li
1✔
75

1✔
76
        switch strings.ToLower(decoder.PackageFraming) {
1✔
77
        case "cobs":
×
78
                p.packageFraming = packageFramingCOBS
×
79
        case "tcobs", "tcobsv1":
1✔
80
                p.packageFraming = packageFramingTCOBS
1✔
81
        case "tcobsv2":
×
82
                p.packageFraming = packageFramingTCOBSv2
×
83
        case "none":
×
84
                p.packageFraming = packageFramingNone
×
85
        default:
×
86
                log.Fatal("Invalid framing switch:\a", decoder.PackageFraming)
×
87
        }
88
        return p
1✔
89
}
90

91
// nextData reads with an inner reader a raw byte stream.
92
//
93
// When less 4 bytes found in the incoming bytes nextPackage nextData without action.
94
// That means the incoming data stream is exhausted and a next try should be started a bit later.
95
// Some arrived bytes are kept internally and concatenated with the following bytes in a next Read.
96
// Afterwards 0 or at least 4 bytes are inside p.B
97
func (p *trexDec) nextData() {
×
98
        m, err := p.In.Read(p.InnerBuffer)      // use p.InnerBuffer as destination read buffer
×
99
        p.B = append(p.B, p.InnerBuffer[:m]...) // merge with leftovers
×
100
        if err != nil && err != io.EOF {        // some serious error
×
101
                log.Fatal("ERROR:internal reader error\a", err) // exit
×
102
        }
×
103
}
104

105
// nextPackage reads with an inner reader a TCOBSv1 encoded byte stream.
106
//
107
// When no terminating 0 is found in the incoming bytes nextPackage returns without action.
108
// That means the incoming data stream is exhausted and a next try should be started a bit later.
109
// Some arrived bytes are kept internally and concatenated with the following bytes in a next Read.
110
// When a terminating 0 is found in the incoming bytes ReadFromCOBS decodes the COBS package
111
// and returns it in b and its len in n. If more data arrived after the first terminating 0,
112
// these are kept internally and concatenated with the following bytes in a next Read.
113
func (p *trexDec) nextPackage() {
4✔
114
        // Here p.IBuf contains none or available bytes, what can be several trice messages.
4✔
115
        // So first try to process p.IBuf.
4✔
116
        index := bytes.IndexByte(p.IBuf, 0) // find terminating 0
4✔
117
        if index == -1 {                    // p.IBuf has no complete COBS data, so try to read more input
8✔
118
                m, err := p.In.Read(p.InnerBuffer)            // use p.InnerBuffer as bytes read buffer
4✔
119
                p.IBuf = append(p.IBuf, p.InnerBuffer[:m]...) // merge with leftovers
4✔
120
                if err != nil && err != io.EOF {              // some serious error
4✔
121
                        log.Fatal("ERROR:internal reader error\a", err) // exit
×
122
                }
×
123
                index = bytes.IndexByte(p.IBuf, 0) // find terminating 0
4✔
124
                if index == -1 {                   // p.IBuf has no complete COBS data, so leave
6✔
125
                        // Even err could be io.EOF, some valid data possibly in p.iBUf.
2✔
126
                        // In case of file input (J-LINK usage) a plug off is not detectable here.
2✔
127
                        return // no terminating 0, nothing to do
2✔
128
                }
2✔
129
        }
130
        if decoder.TestTableMode {
2✔
131
                p.printTestTableLine(index + 1)
×
132
        }
×
133
        // here a complete COBS or TCOBS package exists
134
        if decoder.DebugOut { // Debug output
2✔
135
                fmt.Fprintf(p.W, "%s: ", decoder.PackageFraming)
×
136
                decoder.Dump(p.W, p.IBuf[:index+1])
×
137
        }
×
138

139
        frame := p.IBuf[:index]
2✔
140

2✔
141
        switch p.packageFraming {
2✔
142

143
        case packageFramingCOBS:
×
144
                p.B = p.B0                      // make([]byte, decoder.DefaultSize) // todo: avoid allocation
×
145
                n, e := cobs.Decode(p.B, frame) // if index is 0, an empty buffer is decoded
×
146
                p.IBuf = p.IBuf[index+1:]       // step forward (next package data in p.IBuf now, if any)
×
147
                if e != nil {
×
148
                        if decoder.Verbose {
×
149
                                fmt.Println("\ainconsistent COBS buffer!") // show also terminating 0
×
150
                        }
×
151
                }
152
                p.B = p.B[:n]
×
153

154
        case packageFramingTCOBS:
2✔
155
        repeat:
2✔
156
                p.B = p.B0                       // make([]byte, decoder.DefaultSize) // todo: avoid allocation
2✔
157
                n, e := tcobs.Decode(p.B, frame) // if index is 0, an empty buffer is decoded
2✔
158
                // from merging: p.IBuf = p.IBuf[index+1:]        // step forward (next package data in p.IBuf now, if any)
2✔
159
                if e != nil {
2✔
160
                        fmt.Println("\ainconsistent TCOBSv1 buffer!")
×
161

×
162
                        // remove 3 lines if they exist
×
163
                        s := strings.SplitN(strings.ReplaceAll(string(frame), "\r\n", "\n"), "\n", 4)
×
164
                        var bytesCount int
×
165
                        if len(s) >= 3 {
×
166
                                var newLines int
×
167
                                fmt.Println(s[0])
×
168
                                fmt.Println(s[1])
×
169
                                fmt.Println(s[2])
×
170
                                for _, b := range frame {
×
171
                                        frame = frame[1:]
×
172
                                        bytesCount++
×
173
                                        if b == 10 {
×
174
                                                newLines++
×
175
                                                if newLines == 3 {
×
176
                                                        break
×
177
                                                }
178
                                        }
179
                                        continue
×
180
                                }
181
                                index -= bytesCount
×
182
                                goto repeat
×
183
                        }
184
                        if decoder.Verbose {
×
185
                                fmt.Println(e, "\ainconsistent TCOBSv1 buffer:")
×
186
                                fmt.Println(e, hex.Dump(frame)) // show also terminating 0
×
187
                        }
×
188
                        e = nil
×
189
                        p.B = p.B[:0]
×
190
                        p.IBuf = p.IBuf[index+1:] // step forward (next package data in p.IBuf now, if any) // from merging:
×
191
                } else {
2✔
192
                        p.B = p.B[len(p.B)-n:]    // buffer is filled from the end
2✔
193
                        p.IBuf = p.IBuf[index+1:] // step forward (next package data in p.IBuf now, if any) // from merging:
2✔
194
                }
2✔
195
        default:
×
196
                log.Fatalln("unexpected execution path", p.packageFraming)
×
197
        }
198

199
        if decoder.DebugOut { // Debug output
2✔
200
                fmt.Fprint(p.W, "->TRICE: ")
×
201
                decoder.Dump(p.W, p.B)
×
202
        }
×
203

204
        if cipher.Password != "" { // encrypted
2✔
205
                cipher.Decrypt(p.B, p.B)
×
206
                if decoder.DebugOut { // Debug output
×
207
                        fmt.Fprint(p.W, "-> DEC:  ")
×
208
                        decoder.Dump(p.W, p.B)
×
209
                }
×
210
        }
211
}
212

213
func isZero(bytes []byte) bool {
×
214
        b := byte(0)
×
215
        for _, s := range bytes {
×
216
                b |= s
×
217
        }
×
218
        return b == 0
×
219
}
220

221
func (p *trexDec) removeZeroHiByte(s []byte) (r []byte) {
×
222
        // The package interpreter does not know the number of padding zeroes, so it needs to discard them one by one.
×
223
        // If they are not zero, this is an error.
×
224
        if p.Endian == decoder.BigEndian {
×
225
                // Big endian case: 00 00 AA AA C0 00 -> 00 AA AA C0 00 -> still typeX0 -> AA AA C0 00 -> ok next package
×
226
                if s[0] != 0 {
×
227
                        fmt.Println("unexpected case in line 273", s)
×
228
                }
×
229
                r = s[1:]
×
230
        } else if p.Endian == decoder.LittleEndian {
×
231
                // Little endian case: 00 00 AA AA C0 00 -> 00 AA AA C0 00 -> AA00 signals a valid Trice, but it is not! -> We need to remove the HI byte!
×
232
                if s[1] != 0 {
×
233
                        //log.Fatal("unexpected case", s)
×
234
                        // todo: This needs to be disabled for successfully running all test cases.
×
235
                        // BUT: deferred package framing NONE does not work
×
236
                }
×
237
                r = append(s[:1], s[2:]...)
×
238
        } else {
×
239
                fmt.Println("unexpected case 927346193377", s)
×
240
        }
×
241
        return
×
242
}
243

244
// Read returns a single Trice conversion result or a single error message in b[:n].
245
// Read is the provided read method for TREX decoding and provides next string as byte slice.
246
//
247
// It uses inner reader p.In and internal id look-up table to fill b with a string.
248
// b is a slice of bytes with a len for the max expected string size.
249
// n is the count of read bytes inside b.
250
// Read returns usually one complete trice string or nothing but can return concatenated
251
// trice strings, each ending with a newline despite the last one, when messages added.
252
// Read does not process all internally read complete trice packages to be able later to
253
// separate Trices within one line to keep them separated for color processing.
254
// Therefore, Read needs to be called cyclically even after returning io.EOF to process internal data.
255
// When Read returns n=0, all processable complete trice packages are done,
256
// but the start of a following trice package can be already inside the internal buffer.
257
// In case of a not matching cycle, a warning message in trice format is prefixed.
258
// In case of invalid package data, error messages in trice format are returned and the package is dropped.
259
func (p *trexDec) Read(b []byte) (n int, err error) {
4✔
260
        if p.packageFraming == packageFramingNone {
4✔
261
                p.nextData() // returns all unprocessed data inside p.B
×
262
                p.B0 = p.B   // keep data for re-sync
×
263
        } else {
4✔
264
                if cipher.Password != "" && len(p.B) < 8 && isZero(p.B) {
4✔
265
                        p.B = p.B[:0] // Discard trailing zeroes. ATTENTION: incomplete trice messages containing many zeroes could be problematic here!
×
266
                }
×
267
                if len(p.B) == 1 { // last decoded package exhausted
4✔
268
                        if decoder.Verbose {
×
269
                                fmt.Println("Inconsistent data, discarding last single byte", p.B[0], "from:")
×
270
                                fmt.Println(hex.Dump(p.B))
×
271
                        }
×
272
                        p.B = p.B[:0]
×
273
                }
274
                if len(p.B) == 0 { // last decoded package exhausted
8✔
275
                        p.nextPackage() // returns one decoded package inside p.B
4✔
276
                }
4✔
277
        }
278
        packageSize := len(p.B)
4✔
279
        if packageSize < tyIdSize { // not enough data for a next package
6✔
280
                return
2✔
281
        }
2✔
282
        packed := p.B
2✔
283
        tyId := p.ReadU16(p.B)
2✔
284
        p.B = p.B[tyIdSize:]
2✔
285

2✔
286
        triceType := int(tyId >> decoder.IDBits) // most significant bit are the triceType
2✔
287
        triceID := id.TriceID(0x3FFF & tyId)     // 14 least significant bits are the ID
2✔
288
        decoder.LastTriceID = triceID            // used for showID
2✔
289
        decoder.RecordForStatistics(triceID)     // This is for the "trice log -stat" flag
2✔
290

2✔
291
        //typeX0Handler := "countedString"
2✔
292

2✔
293
        switch triceType {
2✔
294
        case typeS0: // no timestamp
×
295
                decoder.TargetTimestampSize = 0
×
296
        case typeS2: // 16-bit stamp
2✔
297
                decoder.TargetTimestampSize = 2
2✔
298
                if Doubled16BitID { // p.packageFraming == packageFramingNone || cipher.Password != "" {
2✔
299
                        if len(p.B) < 2 {
×
300
                                return // wait for more data
×
301
                        }
×
302

303
                        // Without encoding it needs to be done here.
304
                        // Also encrypted trice messages carry a double 16-bit ID.
305
                        p.B = p.B[tyIdSize:] // When target encoding is done, it removes the double 16-bit ID at the 16-bit timestamp trices.
×
306
                }
307
        case typeS4: // 32-bit stamp
×
308
                decoder.TargetTimestampSize = 4
×
309
        case typeX0: // extended trice type X0
×
310
                if p.packageFraming == packageFramingNone {
×
311
                        // typeX0 is not supported (yet)
×
312
                        if decoder.Verbose {
×
313
                                n += copy(b[n:], fmt.Sprintln("wrn:\aTo try to resync removing zero HI byte from:"))
×
314
                                n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B0)))
×
315
                        }
×
316
                        p.B = p.removeZeroHiByte(p.B0)
×
317
                        return
×
318
                }
319

320
                //  decoder.TargetTimestampSize = 0
321
                //  switch typeX0Handler {
322
                //  case "countedString":
323
                //          len := triceID
324
                //          //n += copy(b[n:], "vintage:")
325
                //          n += copy(b[n:], fmt.Sprintln(string(p.B[:len])))
326
                //          p.B = p.B[len:]
327
                //  default:
328
                //          n += copy(b[n:], fmt.Sprintln("ERROR:\aNo handler for triceType typeX0"))
329
                //  }
330
                //  return n, nil
331

332
                // We can reach here in target TRICE_MULTI_PACK_MODE, when a trice message is followed by several zeroes (up to 7 possible with encryption).
333
                p.B = p.removeZeroHiByte(packed)
×
334
        }
335

336
        if packageSize < tyIdSize+decoder.TargetTimestampSize+ncSize { // for non typeEX trices
2✔
337
                return // not enough data
×
338
        }
×
339

340
        // try to interpret
341
        switch triceType {
2✔
342
        case typeS0:
×
343
                decoder.TargetTimestamp = 0
×
344
        case typeS2: // 16-bit stamp
2✔
345
                decoder.TargetTimestamp = uint64(p.ReadU16(p.B))
2✔
346
        case typeS4: // 32-bit stamp
×
347
                decoder.TargetTimestamp = uint64(p.ReadU32(p.B))
×
348
        default: // typeX0
×
349
                //  switch typeX0Handler {
×
350
                //  case "countedString":
×
351
                //          len := triceID
×
352
                //          n += copy(b[n:], "USER:")
×
353
                //          n += copy(b[n:], fmt.Sprintln(string(p.B[:len])))
×
354
                //          p.B = p.B[len:]
×
355
                //  default:
×
356
                n += copy(b[n:], fmt.Sprintln("ERROR:\atriceType typeX0 not implemented (hint: IDBits value?)"))
×
357
                //  }
×
358
                return n, nil
×
359
        }
360
        //                decoder.TargetTimestampSize = 0
361
        //                switch typeX0Handler {
362
        //                case "countedString":
363
        //                        len := triceID
364
        //                        //n += copy(b[n:], "vintage:")
365
        //                        n += copy(b[n:], fmt.Sprintln(string(p.B[:len])))
366
        //                        p.B = p.B[len:]
367
        //                default:
368
        //                        n += copy(b[n:], fmt.Sprintln("ERROR:\aNo handler for triceType typeX0"))
369
        //                }
370
        //                return n, nil
371
        //
372
        //                //  if p.packageFraming == packageFramingNone {
373
        //                //          // typeX0 is not supported (yet)
374
        //                //          if decoder.Verbose {
375
        //                //                  n += copy(b[n:], fmt.Sprintln("wrn:\aTo try to resync removing zero HI byte from:"))
376
        //                //                  n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B0)))
377
        //                //          }
378
        //                //          p.B = p.removeZeroHiByte(p.B0)
379
        //                //          return
380
        //                //  }
381
        //                // We can reach here in target TRICE_MULTI_PACK_MODE, when a trice message is followed by several zeroes (up to 7 possible with encryption).
382
        //                // p.B = p.removeZeroHiByte(packed)
383
        //        }
384
        //
385
        //        if packageSize < tyIdSize+decoder.TargetTimestampSize+ncSize { // for non typeEX trices
386
        //                return // not enough data
387
        //        }
388
        //
389
        //        // try to interpret
390
        //        switch triceType {
391
        //        case typeS0:
392
        //                decoder.TargetTimestamp = 0
393
        //        case typeS2: // 16-bit stamp
394
        //                decoder.TargetTimestamp = uint64(p.ReadU16(p.B))
395
        //        case typeS4: // 32-bit stamp
396
        //                decoder.TargetTimestamp = uint64(p.ReadU32(p.B))
397
        //        default: // typeX0
398
        //                switch typeX0Handler {
399
        //                case "countedString":
400
        //                        len := triceID
401
        //                        n += copy(b[n:], "USER:")
402
        //                        n += copy(b[n:], fmt.Sprintln(string(p.B[:len])))
403
        //                        p.B = p.B[len:]
404
        //                default:
405
        //                        n += copy(b[n:], fmt.Sprintln("ERROR:\atriceType typeX0 not implemented (hint: IDBits value?)"))
406
        //                }
407
        //                return n, nil
408
        //        }
409

410
        p.B = p.B[decoder.TargetTimestampSize:]
2✔
411

2✔
412
        if len(p.B) < 2 {
2✔
413
                return // wait for more data
×
414
        }
×
415
        nc := p.ReadU16(p.B) // n = number of data bytes (without timestamp), most significant bit is the count encoding, c = cycle
2✔
416
        p.B = p.B[ncSize:]
2✔
417

2✔
418
        var cycle uint8
2✔
419
        if nc>>15 == 1 { // special case: more than data 127 bytes
2✔
420
                // C code: #define TRICE_LCNT(count) TRICE_PUT16( (0x8000 | (count)) );
×
421
                cycle = p.cycle                 // cycle is not transmitted, so set expected value
×
422
                p.ParamSpace = int(0x7FFF & nc) // 15 bit for data byte count excluding timestamp
×
423
        } else {
2✔
424
                // C code: #define TRICE_CNTC(count) TRICE_PUT16( ((count)<<8) | TRICE_CYCLE )
2✔
425
                cycle = uint8(nc)           // low byte is cycle
2✔
426
                p.ParamSpace = int(nc >> 8) // high byte is 7 bit number of bytes for data count excluding timestamp
2✔
427
        }
2✔
428

429
        p.TriceSize = tyIdSize + decoder.TargetTimestampSize + ncSize + p.ParamSpace
2✔
430
        if p.TriceSize > packageSize { //  '>' for multiple trices in one package (case TriceOutMultiPackMode), todo: discuss all possible variants
2✔
431
                if p.packageFraming == packageFramingNone {
×
432
                        if decoder.Verbose {
×
433
                                n += copy(b[n:], fmt.Sprintln("wrn:\adiscarding first byte", p.B0[0], "from:"))
×
434
                                n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B0)))
×
435
                        }
×
436
                        p.B0 = p.B0[1:] // discard first byte and try again
×
437
                        p.B = p.B0
×
438
                        return
×
439
                }
440
                if decoder.Verbose {
×
441
                        n += copy(b[n:], fmt.Sprintln("ERROR:\apackage size", packageSize, "is <", p.TriceSize, " - ignoring package:"))
×
442
                        n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B)))
×
443
                        n += copy(b[n:], fmt.Sprintln("tyIdSize=", tyIdSize, "tsSize=", decoder.TargetTimestampSize, "ncSize=", ncSize, "ParamSpae=", p.ParamSpace))
×
444
                        n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
445
                }
×
446
                p.B = p.B[len(p.B):] // discard buffer
×
447
        }
448
        if SingleFraming && p.TriceSize != packageSize {
2✔
449
                if decoder.Verbose {
×
450
                        n += copy(b[n:], fmt.Sprintln("ERROR:\asingle framed package size", packageSize, "is !=", p.TriceSize, " - ignoring package:"))
×
451
                        n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B)))
×
452
                        n += copy(b[n:], fmt.Sprintln("tyIdSize=", tyIdSize, "tsSize=", decoder.TargetTimestampSize, "ncSize=", ncSize, "ParamSpae=", p.ParamSpace))
×
453
                        n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
454
                }
×
455
                p.B = p.B[len(p.B):] // discard buffer
×
456
        }
457

458
        // cycle counter automatic & check
459
        if cycle == 0xc0 && p.cycle != 0xc0 && decoder.InitialCycle { // with cycle counter and seems to be a target reset
2✔
460
                n += copy(b[n:], fmt.Sprintln("warning:\a   Target Reset?   "))
×
461
                p.cycle = cycle + 1 // adjust cycle
×
462
                decoder.InitialCycle = false
×
463
        }
×
464
        if cycle == 0xc0 && p.cycle != 0xc0 && !decoder.InitialCycle { // with cycle counter and seems to be a target reset
2✔
465
                //n += copy(b[n:], fmt.Sprintln("info:   Target Reset?   ")) // todo: This line is ok with cycle counter but not without cycle counter
×
466
                p.cycle = cycle + 1 // adjust cycle
×
467
        }
×
468
        if cycle == 0xc0 && p.cycle == 0xc0 && decoder.InitialCycle { // with or without cycle counter and seems to be a target reset
3✔
469
                //n += copy(b[n:], fmt.Sprintln("warning:   Restart?   "))
1✔
470
                p.cycle = cycle + 1 // adjust cycle
1✔
471
                decoder.InitialCycle = false
1✔
472
        }
1✔
473
        if cycle == 0xc0 && p.cycle == 0xc0 && !decoder.InitialCycle { // with or without cycle counter and seems to be a normal case
2✔
474
                p.cycle = cycle + 1 // adjust cycle
×
475
        }
×
476
        if cycle != 0xc0 && !DisableCycleErrors { // with cycle counter and s.th. lost
3✔
477
                if cycle != p.cycle { // no cycle check for 0xc0 to avoid messages on every target reset and when no cycle counter is active
1✔
478
                        n += copy(b[n:], fmt.Sprintln("CYCLE_ERROR:\a", cycle, "!=", p.cycle, " (count=", emitter.TagEvents("CYCLE_ERROR")+1, ")"))
×
479
                        n += copy(b[n:], "                                         ") // len of location information plus stamp: 41 spaces - see NewlineIndent below - todo: make it generic
×
480
                        p.cycle = cycle                                               // adjust cycle
×
481
                }
×
482
                decoder.InitialCycle = false
1✔
483
                p.cycle++
1✔
484
        }
485

486
        var ok bool
2✔
487
        p.LutMutex.RLock()
2✔
488
        p.Trice, ok = p.Lut[triceID]
2✔
489
        if AddNewlineToEachTriceMessage {
2✔
490
                p.Trice.Strg += `\n` // this adds a newline to each single Trice message
×
491
        }
×
492
        p.LutMutex.RUnlock()
2✔
493
        if !ok {
2✔
494
                if p.packageFraming == packageFramingNone {
×
495
                        if decoder.Verbose {
×
496
                                n += copy(b[n:], fmt.Sprintln("wrn:\adiscarding first byte", p.B0[0], "from:"))
×
497
                                n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B0)))
×
498
                        }
×
499
                        p.B0 = p.B0[1:] // discard first byte and try again
×
500
                        p.B = p.B0
×
501
                } else {
×
502
                        n += copy(b[n:], fmt.Sprintln("WARNING:\aunknown ID ", triceID, "- ignoring trice ending with:"))
×
503
                        n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B)))
×
504
                        n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
505
                        p.B = p.B[:0] // discard all
×
506
                }
×
507
                return
×
508
        }
509

510
        n += p.sprintTrice(b[n:]) // use param info
2✔
511
        if len(p.B) < p.ParamSpace {
2✔
512
                if p.packageFraming == packageFramingNone {
×
513
                        if decoder.Verbose {
×
514
                                n += copy(b[n:], fmt.Sprintln("wrn:discarding first byte", p.B0[0], "from:"))
×
515
                                n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B0)))
×
516
                        }
×
517
                        p.B0 = p.B0[1:] // discard first byte and try again
×
518
                        p.B = p.B0
×
519
                } else {
×
520
                        n += copy(b[n:], fmt.Sprintln("ERROR:ignoring data garbage:"))
×
521
                        n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B)))
×
522
                        n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
523
                        p.B = p.B[:0] // discard all
×
524
                }
×
525
        } else {
2✔
526
                if p.packageFraming != packageFramingNone { // COBS | TCOBS are exact
4✔
527
                        p.B = p.B[p.ParamSpace:] // drop param info
2✔
528
                } else { // no package framing
2✔
529
                        padding := (p.ParamSpace + 3) & ^3
×
530
                        if padding <= len(p.B) {
×
531
                                p.B = p.B[padding:]
×
532
                        } else {
×
533
                                // n += copy(b[n:], fmt.Sprintln("wrn: cannot discard padding bytes", ))
×
534
                        }
×
535
                }
536
        }
537
        return
2✔
538
}
539

540
// sprintTrice writes a trice string or appropriate message into b and returns that len.
541
//
542
// p.Trice.Type is the received trice, in fact the name from til.json.
543
func (p *trexDec) sprintTrice(b []byte) (n int) {
2✔
544

2✔
545
        isSAlias := strings.HasPrefix(p.Trice.Strg, id.SAliasStrgPrefix) && strings.HasSuffix(p.Trice.Strg, id.SAliasStrgSuffix)
2✔
546
        if isSAlias { // A SAlias Strg is covered with id.SAliasStrgPrefix and id.SAliasStrgSuffix in til.json and it needs to be replaced with "%s" here.
2✔
547
                p.Trice.Strg = "%s" // See appropriate comment inside insertTriceIDs().
×
548
        }
×
549

550
        p.pFmt, p.u = decoder.UReplaceN(p.Trice.Strg)
2✔
551

2✔
552
        // remove Assert* from triceAssert* name if found
2✔
553
        before, _, found := strings.Cut(p.Trice.Type, "Assert")
2✔
554
        if found {
2✔
555
                p.Trice.Type = strings.TrimSpace(before)
×
556
        }
×
557

558
        triceType, err := id.ConstructFullTriceInfo(p.Trice.Type, len(p.u))
2✔
559

2✔
560
        if err != nil {
2✔
561
                n += copy(b[n:], fmt.Sprintln("err:ConstructFullTriceInfo failed with:", p.Trice.Type, len(p.B), "- ignoring package:"))
×
562
                return
×
563
        }
×
564
        ucTriceTypeReceived := strings.ToUpper(p.Trice.Type)   // examples: TRICE_S,   TRICE,   TRICE32,   TRICE16_2
2✔
565
        ucTriceTypeReconstructed := strings.ToUpper(triceType) // examples: TRICE32_S, TRICE0,  TRICE32_4, TRICE16_2
2✔
566
        for _, s := range cobsFunctionPtrList {                // walk through the list and try to find a match for execution
45✔
567
                if s.triceType == ucTriceTypeReconstructed || s.triceType == ucTriceTypeReceived { // match list entry "TRICE..."
45✔
568
                        if len(p.B) < p.ParamSpace {
2✔
569
                                n += copy(b[n:], fmt.Sprintln("err:len(p.B) =", len(p.B), "< p.ParamSpace = ", p.ParamSpace, "- ignoring package:"))
×
570
                                n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B[:len(p.B)])))
×
571
                                n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
572
                                return
×
573
                        }
×
574
                        if p.ParamSpace != (s.bitWidth>>3)*s.paramCount {
2✔
575
                                specialCases := []string{
×
576
                                        "TRICES", "TRICEN", "TRICEB", "TRICEF",
×
577
                                        "TRICE8B", "TRICE16B", "TRICE32B", "TRICE64B",
×
578
                                        "TRICE8F", "TRICE16F", "TRICE32F", "TRICE64F",
×
579

×
580
                                        "TRICE_S", "TRICE_N", "TRICE_B", "TRICE_F",
×
581
                                        "TRICE8_B", "TRICE16_B", "TRICE32_B", "TRICE64_B",
×
582
                                        "TRICE8_F", "TRICE16_F", "TRICE32_F", "TRICE64_F",
×
583
                                }
×
584
                                tt := strings.ToUpper(s.triceType)
×
585
                                for _, casus := range specialCases {
×
586
                                        if tt == casus {
×
587
                                                goto ignoreSpecialCase
×
588
                                        }
589
                                }
590
                                n += copy(b[n:], fmt.Sprintln("err:s.triceType =", s.triceType, "ParamSpace =", p.ParamSpace, "not matching with bitWidth ", s.bitWidth, "and paramCount", s.paramCount, "- ignoring package:"))
×
591
                                n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B[:len(p.B)])))
×
592
                                n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
593
                                return
×
594
                        }
595
                ignoreSpecialCase:
596
                        ss := strings.Split(p.pFmt, `\n`)
2✔
597
                        if len(ss) >= 3 { // at least one "\n" before "\n" line end
2✔
598
                                if decoder.NewlineIndent == -1 { // auto sense
×
599
                                        decoder.NewlineIndent = 12 + 1 // todo: strings.SplitN & len(decoder.TargetStamp0) // 12
×
600
                                        if !(id.LIFnJSON == "off" || id.LIFnJSON == "none") {
×
601
                                                decoder.NewlineIndent += 28 /* todo: length(decoder.LocationInformationFormatString), see https://stackoverflow.com/questions/32987215/find-numbers-in-string-using-golang-regexp*/
×
602
                                                // todo: split channel info with format specifiers too, example: ["msg:%d\nsignal:%x %u\n", p0, p1, p2] -> ["msg:%d\n", p0] && ["signal:%x %u\n", p1, p2]
×
603
                                        }
×
604
                                        if decoder.ShowID != "" {
×
605
                                                decoder.NewlineIndent += 5 // todo: automatic
×
606
                                        }
×
607
                                }
608
                                skip := `\n`
×
609
                                spaces := decoder.NewlineIndent
×
610
                                for spaces > 0 {
×
611
                                        skip += " "
×
612
                                        spaces--
×
613
                                }
×
614
                                p.pFmt = strings.Join(ss[:], skip)
×
615
                                p.pFmt = strings.TrimRight(p.pFmt, " ")
×
616
                        }
617

618
                        n += s.triceFn(p, b, s.bitWidth, s.paramCount) // match found, call handler
2✔
619
                        return
2✔
620
                }
621
        }
622
        n += copy(b[n:], fmt.Sprintln("err:Unknown trice.Type:", p.Trice.Type, "and", triceType, "not matching - ignoring trice data:"))
×
623
        n += copy(b[n:], fmt.Sprintln(hex.Dump(p.B[:p.ParamSpace])))
×
624
        n += copy(b[n:], fmt.Sprintln(decoder.Hints))
×
625
        return
×
626
}
627

628
// triceTypeFn is the type for cobsFunctionPtrList elements.
629
type triceTypeFn struct {
630
        triceType  string                                              // triceType describes if parameters, the parameter bit width or if the parameter is a string.
631
        triceFn    func(p *trexDec, b []byte, bitwidth, count int) int // triceFn performs the conversion to the output string.
632
        ParamSpace int                                                 // ParamSpace is the count of bytes allocated for the parameters.
633
        bitWidth   int                                                 // bitWidth is the individual parameter width.
634
        paramCount int                                                 // paramCount is the amount pf parameters for the format string, which must match the count of format specifiers.
635
}
636

637
// cobsFunctionPtrList is a function pointer list.
638
var cobsFunctionPtrList = [...]triceTypeFn{
639
        {"TRICE_0", (*trexDec).trice0, 0, 0, 0},
640
        {"TRICE8_1", (*trexDec).unSignedOrSignedOut, 1, 8, 1},
641
        {"TRICE8_2", (*trexDec).unSignedOrSignedOut, 2, 8, 2},
642
        {"TRICE8_3", (*trexDec).unSignedOrSignedOut, 3, 8, 3},
643
        {"TRICE8_4", (*trexDec).unSignedOrSignedOut, 4, 8, 4},
644
        {"TRICE8_5", (*trexDec).unSignedOrSignedOut, 5, 8, 5},
645
        {"TRICE8_6", (*trexDec).unSignedOrSignedOut, 6, 8, 6},
646
        {"TRICE8_7", (*trexDec).unSignedOrSignedOut, 7, 8, 7},
647
        {"TRICE8_8", (*trexDec).unSignedOrSignedOut, 8, 8, 8},
648
        {"TRICE8_9", (*trexDec).unSignedOrSignedOut, 9, 8, 9},
649
        {"TRICE8_10", (*trexDec).unSignedOrSignedOut, 10, 8, 10},
650
        {"TRICE8_11", (*trexDec).unSignedOrSignedOut, 11, 8, 11},
651
        {"TRICE8_12", (*trexDec).unSignedOrSignedOut, 12, 8, 12},
652
        {"TRICE16_1", (*trexDec).unSignedOrSignedOut, 2, 16, 1},
653
        {"TRICE16_2", (*trexDec).unSignedOrSignedOut, 4, 16, 2},
654
        {"TRICE16_3", (*trexDec).unSignedOrSignedOut, 6, 16, 3},
655
        {"TRICE16_4", (*trexDec).unSignedOrSignedOut, 8, 16, 4},
656
        {"TRICE16_5", (*trexDec).unSignedOrSignedOut, 10, 16, 5},
657
        {"TRICE16_6", (*trexDec).unSignedOrSignedOut, 12, 16, 6},
658
        {"TRICE16_7", (*trexDec).unSignedOrSignedOut, 14, 16, 7},
659
        {"TRICE16_8", (*trexDec).unSignedOrSignedOut, 16, 16, 8},
660
        {"TRICE16_9", (*trexDec).unSignedOrSignedOut, 18, 16, 9},
661
        {"TRICE16_10", (*trexDec).unSignedOrSignedOut, 20, 16, 10},
662
        {"TRICE16_11", (*trexDec).unSignedOrSignedOut, 22, 16, 11},
663
        {"TRICE16_12", (*trexDec).unSignedOrSignedOut, 24, 16, 12},
664
        {"TRICE32_1", (*trexDec).unSignedOrSignedOut, 4, 32, 1},
665
        {"TRICE32_2", (*trexDec).unSignedOrSignedOut, 8, 32, 2},
666
        {"TRICE32_3", (*trexDec).unSignedOrSignedOut, 12, 32, 3},
667
        {"TRICE32_4", (*trexDec).unSignedOrSignedOut, 16, 32, 4},
668
        {"TRICE32_5", (*trexDec).unSignedOrSignedOut, 20, 32, 5},
669
        {"TRICE32_6", (*trexDec).unSignedOrSignedOut, 24, 32, 6},
670
        {"TRICE32_7", (*trexDec).unSignedOrSignedOut, 28, 32, 7},
671
        {"TRICE32_8", (*trexDec).unSignedOrSignedOut, 32, 32, 8},
672
        {"TRICE32_9", (*trexDec).unSignedOrSignedOut, 36, 32, 9},
673
        {"TRICE32_10", (*trexDec).unSignedOrSignedOut, 40, 32, 10},
674
        {"TRICE32_11", (*trexDec).unSignedOrSignedOut, 44, 32, 11},
675
        {"TRICE32_12", (*trexDec).unSignedOrSignedOut, 48, 32, 12},
676
        {"TRICE64_1", (*trexDec).unSignedOrSignedOut, 8, 64, 1},
677
        {"TRICE64_2", (*trexDec).unSignedOrSignedOut, 16, 64, 2},
678
        {"TRICE64_3", (*trexDec).unSignedOrSignedOut, 24, 64, 3},
679
        {"TRICE64_4", (*trexDec).unSignedOrSignedOut, 32, 64, 4},
680
        {"TRICE64_5", (*trexDec).unSignedOrSignedOut, 40, 64, 5},
681
        {"TRICE64_6", (*trexDec).unSignedOrSignedOut, 48, 64, 6},
682
        {"TRICE64_7", (*trexDec).unSignedOrSignedOut, 56, 64, 7},
683
        {"TRICE64_8", (*trexDec).unSignedOrSignedOut, 64, 64, 8},
684
        {"TRICE64_9", (*trexDec).unSignedOrSignedOut, 72, 64, 9},
685
        {"TRICE64_10", (*trexDec).unSignedOrSignedOut, 80, 64, 10},
686
        {"TRICE64_11", (*trexDec).unSignedOrSignedOut, 88, 64, 11},
687
        {"TRICE64_12", (*trexDec).unSignedOrSignedOut, 96, 64, 12},
688

689
        {"TRICES", (*trexDec).triceS, -1, 0, 0},
690
        {"TRICEN", (*trexDec).triceN, -1, 0, 0},
691

692
        {"TRICE8F", (*trexDec).trice8F, -1, 0, 0},
693
        {"TRICE16F", (*trexDec).trice16F, -1, 0, 0},
694
        {"TRICE32F", (*trexDec).trice32F, -1, 0, 0},
695
        {"TRICE64F", (*trexDec).trice64F, -1, 0, 0},
696

697
        {"TRICE8B", (*trexDec).trice8B, -1, 0, 0},
698
        {"TRICE16B", (*trexDec).trice16B, -1, 0, 0},
699
        {"TRICE32B", (*trexDec).trice32B, -1, 0, 0},
700
        {"TRICE64B", (*trexDec).trice64B, -1, 0, 0},
701
}
702

703
// triceN converts dynamic strings.
704
func (p *trexDec) triceN(b []byte, _ int, _ int) int {
×
705
        s := string(p.B[:p.ParamSpace])
×
706
        // todo: evaluate p.Trice.Strg, use p.SLen and do whatever should be done
×
707
        return copy(b, fmt.Sprintf(p.Trice.Strg, s))
×
708
}
×
709

710
// triceS converts dynamic strings.
711
func (p *trexDec) triceS(b []byte, _ int, _ int) int {
×
712
        s := string(p.B[:p.ParamSpace])
×
713
        return copy(b, fmt.Sprintf(p.Trice.Strg, s))
×
714
}
×
715

716
// triceB converts dynamic buffers.
717
func (p *trexDec) trice8B(b []byte, _ int, _ int) (n int) {
×
718
        if decoder.DebugOut {
×
719
                fmt.Fprintln(p.W, p.B)
×
720
        }
×
721
        s := p.B[:p.ParamSpace]
×
722
        before, after, found := strings.Cut(p.Trice.Strg, ":")
×
723
        if found {
×
724
                n += copy(b[n:], fmt.Sprint(before+":")) // print channel
×
725
        } else {
×
726
                after = p.Trice.Strg
×
727
        }
×
728

729
        noNewline := strings.TrimSuffix(after, `\n`)
×
730

×
731
        for i := 0; i < len(s); i++ {
×
732
                n += copy(b[n:], fmt.Sprintf(noNewline, s[i]))
×
733
        }
×
734
        if len(noNewline) < len(after) { // strings.TrimSuffix removed a newline
×
735
                n += copy(b[n:], fmt.Sprintln()) // so add it finally
×
736
        }
×
737
        return
×
738
}
739

740
// trice16B converts dynamic buffers.
741
func (p *trexDec) trice16B(b []byte, _ int, _ int) (n int) {
×
742
        if decoder.DebugOut {
×
743
                fmt.Fprintln(p.W, p.B)
×
744
        }
×
745
        s := p.B[:p.ParamSpace]
×
746

×
747
        before, after, found := strings.Cut(p.Trice.Strg, ":")
×
748
        if found {
×
749
                n += copy(b[n:], fmt.Sprint(before+":")) // print channel
×
750
        } else {
×
751
                after = p.Trice.Strg
×
752
        }
×
753

754
        noNewline := strings.TrimSuffix(after, `\n`)
×
755

×
756
        for i := 0; i < len(s); i += 2 {
×
757
                n += copy(b[n:], fmt.Sprintf(noNewline, binary.LittleEndian.Uint16(s[i:])))
×
758
        }
×
759
        if len(noNewline) < len(after) { // strings.TrimSuffix removed a newline
×
760
                n += copy(b[n:], fmt.Sprintln()) // so add it finally
×
761
        }
×
762

763
        return
×
764
}
765

766
// trice32B converts dynamic buffers.
767
func (p *trexDec) trice32B(b []byte, _ int, _ int) (n int) {
×
768
        if decoder.DebugOut {
×
769
                fmt.Fprintln(p.W, p.B)
×
770
        }
×
771
        s := p.B[:p.ParamSpace]
×
772

×
773
        before, after, found := strings.Cut(p.Trice.Strg, ":")
×
774
        if found {
×
775
                n += copy(b[n:], fmt.Sprint(before+":")) // print channel
×
776
        } else {
×
777
                after = p.Trice.Strg
×
778
        }
×
779

780
        noNewline := strings.TrimSuffix(after, `\n`)
×
781

×
782
        for i := 0; i < len(s); i += 4 {
×
783
                n += copy(b[n:], fmt.Sprintf(noNewline, binary.LittleEndian.Uint32(s[i:])))
×
784
        }
×
785
        if len(noNewline) < len(after) { // strings.TrimSuffix removed a newline
×
786
                n += copy(b[n:], fmt.Sprintln()) // so add it finally
×
787
        }
×
788
        return
×
789
}
790

791
// trice64B converts dynamic buffers.
792
func (p *trexDec) trice64B(b []byte, _ int, _ int) (n int) {
×
793
        if decoder.DebugOut {
×
794
                fmt.Fprintln(p.W, p.B)
×
795
        }
×
796
        s := p.B[:p.ParamSpace]
×
797

×
798
        before, after, found := strings.Cut(p.Trice.Strg, ":")
×
799
        if found {
×
800
                n += copy(b[n:], fmt.Sprint(before+":")) // print channel
×
801
        } else {
×
802
                after = p.Trice.Strg
×
803
        }
×
804

805
        noNewline := strings.TrimSuffix(after, `\n`)
×
806

×
807
        for i := 0; i < len(s); i += 8 {
×
808
                n += copy(b[n:], fmt.Sprintf(noNewline, binary.LittleEndian.Uint64(s[i:])))
×
809
        }
×
810
        if len(noNewline) < len(after) { // strings.TrimSuffix removed a newline
×
811
                n += copy(b[n:], fmt.Sprintln()) // so add it finally
×
812
        }
×
813
        return
×
814
}
815

816
// trice8F display function call with 8-bit parameters.
817
func (p *trexDec) trice8F(b []byte, _ int, _ int) (n int) {
×
818
        if decoder.DebugOut {
×
819
                fmt.Fprintln(p.W, p.B)
×
820
        }
×
821
        s := p.B[:p.ParamSpace]
×
822
        n += copy(b[n:], fmt.Sprint(p.Trice.Strg))
×
823
        for i := 0; i < len(s); i++ {
×
824
                n += copy(b[n:], fmt.Sprintf("(%02x)", s[i]))
×
825
        }
×
826
        n += copy(b[n:], fmt.Sprintln())
×
827
        return
×
828
}
829

830
// trice16F display function call with 16-bit parameters.
831
func (p *trexDec) trice16F(b []byte, _ int, _ int) (n int) {
×
832
        if decoder.DebugOut {
×
833
                fmt.Fprintln(p.W, p.B)
×
834
        }
×
835
        s := p.B[:p.ParamSpace]
×
836
        n += copy(b[n:], fmt.Sprint(p.Trice.Strg))
×
837
        for i := 0; i < len(s); i += 2 {
×
838
                n += copy(b[n:], fmt.Sprintf("(%04x)", binary.LittleEndian.Uint16(s[i:])))
×
839
        }
×
840
        n += copy(b[n:], fmt.Sprintln())
×
841
        return
×
842
}
843

844
// trice32F display function call with 32-bit parameters.
845
func (p *trexDec) trice32F(b []byte, _ int, _ int) (n int) {
×
846
        if decoder.DebugOut {
×
847
                fmt.Fprintln(p.W, p.B)
×
848
        }
×
849
        s := p.B[:p.ParamSpace]
×
850
        n += copy(b[n:], fmt.Sprint(p.Trice.Strg))
×
851
        for i := 0; i < len(s); i += 4 {
×
852
                n += copy(b[n:], fmt.Sprintf("(%08x)", binary.LittleEndian.Uint32(s[i:])))
×
853
        }
×
854
        n += copy(b[n:], fmt.Sprintln())
×
855
        return
×
856
}
857

858
// trice64F display function call with 64-bit parameters.
859
func (p *trexDec) trice64F(b []byte, _ int, _ int) (n int) {
×
860
        if decoder.DebugOut {
×
861
                fmt.Fprintln(p.W, p.B)
×
862
        }
×
863
        s := p.B[:p.ParamSpace]
×
864
        n += copy(b[n:], fmt.Sprint(p.Trice.Strg))
×
865
        for i := 0; i < len(s); i += 8 {
×
866
                n += copy(b[n:], fmt.Sprintf("(%016x)", binary.LittleEndian.Uint64(s[i:])))
×
867
        }
×
868
        n += copy(b[n:], fmt.Sprintln())
×
869
        return
×
870
}
871

872
// trice0 prints the trice format string.
873
func (p *trexDec) trice0(b []byte, _ int, _ int) int {
×
874
        return copy(b, fmt.Sprint(p.pFmt))
×
875
}
×
876

877
// unSignedOrSignedOut prints p.B according to the format string.
878
func (p *trexDec) unSignedOrSignedOut(b []byte, bitwidth, count int) int {
2✔
879
        if len(p.u) != count {
2✔
880
                return copy(b, fmt.Sprintln("ERROR: Invalid format specifier count inside", p.Trice.Type, p.Trice.Strg))
×
881
        }
×
882
        v := make([]interface{}, 32768) // theoretical 2^15 bytes could arrive
2✔
883
        switch bitwidth {
2✔
884
        case 8:
×
885
                for i, f := range p.u {
×
886
                        switch f {
×
887
                        case decoder.UnsignedFormatSpecifier, decoder.PointerFormatSpecifier: // see comment inside decoder.UReplaceN
×
888
                                v[i] = p.B[i]
×
889
                        case decoder.SignedFormatSpecifier:
×
890
                                v[i] = int8(p.B[i])
×
891
                        case decoder.BooleanFormatSpecifier:
×
892
                                v[i] = p.B[i] != 0
×
893
                        default:
×
894
                                return copy(b, fmt.Sprintln("ERROR: Invalid format specifier (float?) inside", p.Trice.Type, p.Trice.Strg))
×
895
                        }
896
                }
897
        case 16:
1✔
898
                for i, f := range p.u {
2✔
899
                        n := p.ReadU16(p.B[2*i:])
1✔
900
                        switch f {
1✔
901
                        case decoder.UnsignedFormatSpecifier, decoder.PointerFormatSpecifier: // see comment inside decoder.UReplaceN
×
902
                                v[i] = n
×
903
                        case decoder.SignedFormatSpecifier:
1✔
904
                                v[i] = int16(n)
1✔
905
                        case decoder.BooleanFormatSpecifier:
×
906
                                v[i] = n != 0
×
907
                        default:
×
908
                                return copy(b, fmt.Sprintln("ERROR: Invalid format specifier (float?) inside", p.Trice.Type, p.Trice.Strg))
×
909
                        }
910
                }
911
        case 32:
1✔
912
                for i, f := range p.u {
5✔
913
                        n := p.ReadU32(p.B[4*i:])
4✔
914
                        switch f {
4✔
915
                        case decoder.UnsignedFormatSpecifier, decoder.PointerFormatSpecifier: // see comment inside decoder.UReplaceN
×
916
                                v[i] = n
×
917
                        case decoder.SignedFormatSpecifier:
4✔
918
                                v[i] = int32(n)
4✔
919
                        case decoder.FloatFormatSpecifier:
×
920
                                v[i] = math.Float32frombits(n)
×
921
                        case decoder.BooleanFormatSpecifier:
×
922
                                v[i] = n != 0
×
923
                        default:
×
924
                                return copy(b, fmt.Sprintln("ERROR: Invalid format specifier inside", p.Trice.Type, p.Trice.Strg))
×
925
                        }
926
                }
927
        case 64:
×
928
                for i, f := range p.u {
×
929
                        n := p.ReadU64(p.B[8*i:])
×
930
                        switch f {
×
931
                        case decoder.UnsignedFormatSpecifier, decoder.PointerFormatSpecifier: // see comment inside decoder.UReplaceN
×
932
                                v[i] = n
×
933
                        case decoder.SignedFormatSpecifier:
×
934
                                v[i] = int64(n)
×
935
                        case decoder.FloatFormatSpecifier:
×
936
                                v[i] = math.Float64frombits(n)
×
937
                        case decoder.BooleanFormatSpecifier:
×
938
                                v[i] = n != 0
×
939
                        default:
×
940
                                return copy(b, fmt.Sprintln("ERROR: Invalid format specifier inside", p.Trice.Type, p.Trice.Strg))
×
941
                        }
942
                }
943
        }
944
        return copy(b, fmt.Sprintf(p.pFmt, v[:len(p.u)]...))
2✔
945
}
946

947
var testTableVirgin = true
948

949
// printTestTableLine is used to generate testdata
950
func (p *trexDec) printTestTableLine(n int) {
×
951
        if emitter.NextLine || testTableVirgin {
×
952
                emitter.NextLine = false
×
953
                testTableVirgin = false
×
954
                fmt.Printf("{ []byte{ ")
×
955
        }
×
956
        for _, b := range p.IBuf[0:n] { // just to see trice bytes per trice
×
957
                fmt.Printf("%3d,", b)
×
958
        }
×
959
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc