You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2024/09/30 15:58:37 UTC

(plc4x) 06/06: feat(plc4go/spi): add pos/length footer option to WriteBufferBoxBased

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 4de3d55fc7682c42e3c69b0ecde31e75b2af5dfe
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Sep 30 17:58:22 2024 +0200

    feat(plc4go/spi): add pos/length footer option to WriteBufferBoxBased
---
 plc4go/spi/utils/WriteBufferBoxBased.go | 146 ++++++++++++++++++++++++--------
 1 file changed, 109 insertions(+), 37 deletions(-)

diff --git a/plc4go/spi/utils/WriteBufferBoxBased.go b/plc4go/spi/utils/WriteBufferBoxBased.go
index 5dda66a254..28078ce4f3 100644
--- a/plc4go/spi/utils/WriteBufferBoxBased.go
+++ b/plc4go/spi/utils/WriteBufferBoxBased.go
@@ -25,6 +25,7 @@ import (
 	"encoding/binary"
 	"fmt"
 	"math/big"
+	"strconv"
 
 	"github.com/pkg/errors"
 )
@@ -34,20 +35,35 @@ type WriteBufferBoxBased interface {
 	GetBox() AsciiBox
 }
 
-func NewWriteBufferBoxBased() WriteBufferBoxBased {
-	return NewWriteBufferBoxBasedWithOptions(false, false)
-}
-
-func NewWriteBufferBoxBasedWithOptions(mergeSingleBoxes bool, omitEmptyBoxes bool) WriteBufferBoxBased {
-	return &boxedWriteBuffer{
+func NewWriteBufferBoxBased(opts ...func(buffer *boxedWriteBuffer)) WriteBufferBoxBased {
+	wb := &boxedWriteBuffer{
 		List:                list.New(),
 		desiredWidth:        120,
 		currentWidth:        118,
-		mergeSingleBoxes:    mergeSingleBoxes,
-		omitEmptyBoxes:      omitEmptyBoxes,
 		asciiBoxWriter:      AsciiBoxWriterDefault,
 		asciiBoxWriterLight: AsciiBoxWriterLight,
 	}
+	for _, opt := range opts {
+		opt(wb)
+	}
+	return wb
+}
+
+// Deprecated: use WithWriteBufferBoxBasedMergeSingleBoxes and WithWriteBufferBoxBasedOmitEmptyBoxes
+func NewWriteBufferBoxBasedWithOptions(mergeSingleBoxes bool, omitEmptyBoxes bool) WriteBufferBoxBased {
+	return NewWriteBufferBoxBased(WithWriteBufferBoxBasedMergeSingleBoxes(), WithWriteBufferBoxBasedOmitEmptyBoxes())
+}
+
+func WithWriteBufferBoxBasedMergeSingleBoxes() func(*boxedWriteBuffer) {
+	return func(wb *boxedWriteBuffer) {
+		wb.mergeSingleBoxes = true
+	}
+}
+
+func WithWriteBufferBoxBasedOmitEmptyBoxes() func(*boxedWriteBuffer) {
+	return func(wb *boxedWriteBuffer) {
+		wb.omitEmptyBoxes = true
+	}
 }
 
 ///////////////////////////////////////
@@ -59,13 +75,14 @@ func NewWriteBufferBoxBasedWithOptions(mergeSingleBoxes bool, omitEmptyBoxes boo
 type boxedWriteBuffer struct {
 	BufferCommons
 	*list.List
-	desiredWidth        int
-	currentWidth        int
-	mergeSingleBoxes    bool
-	omitEmptyBoxes      bool
-	asciiBoxWriter      AsciiBoxWriter
-	asciiBoxWriterLight AsciiBoxWriter
-	pos                 uint
+	desiredWidth         int
+	currentWidth         int
+	mergeSingleBoxes     bool
+	omitEmptyBoxes       bool
+	printPosLengthFooter bool
+	asciiBoxWriter       AsciiBoxWriter
+	asciiBoxWriterLight  AsciiBoxWriter
+	pos                  uint
 }
 
 var _ WriteBuffer = (*boxedWriteBuffer)(nil)
@@ -107,7 +124,9 @@ func (b *boxedWriteBuffer) WriteBit(logicalName string, value bool, writerArgs .
 	if value {
 		asInt = 1
 	}
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("b%d %t%s", asInt, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("b%d %t%s", asInt, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(1)))
+	b.PushBack(box)
 	b.move(1)
 	return nil
 }
@@ -118,7 +137,9 @@ func (b *boxedWriteBuffer) WriteByte(logicalName string, value byte, writerArgs
 	if value < 32 || value > 126 {
 		printSafeChar = '.'
 	}
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#02x '%c'%s", value, printSafeChar, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#02x '%c'%s", value, printSafeChar, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(8)))
+	b.PushBack(box)
 	b.move(8)
 	return nil
 }
@@ -128,98 +149,126 @@ func (b *boxedWriteBuffer) WriteByteArray(logicalName string, data []byte, write
 	if additionalStringRepresentation != "" {
 		additionalStringRepresentation += "\n"
 	}
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%s%s", additionalStringRepresentation, Dump(data)), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%s%s", additionalStringRepresentation, Dump(data))
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(len(data)*8)))
+	b.PushBack(box)
 	b.move(uint(len(data) * 8))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteUint8(logicalName string, bitLength uint8, value uint8, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteUint16(logicalName string, bitLength uint8, value uint16, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteUint32(logicalName string, bitLength uint8, value uint32, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteUint64(logicalName string, bitLength uint8, value uint64, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteInt8(logicalName string, bitLength uint8, value int8, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteInt16(logicalName string, bitLength uint8, value int16, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteInt32(logicalName string, bitLength uint8, value int32, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteInt64(logicalName string, bitLength uint8, value int64, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteBigInt(logicalName string, bitLength uint8, value *big.Int, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %d%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteFloat32(logicalName string, bitLength uint8, value float32, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %f%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %f%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteFloat64(logicalName string, bitLength uint8, value float64, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %f%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %f%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteBigFloat(logicalName string, bitLength uint8, value *big.Float, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%#0*x %f%s", bitLength/4, value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%#0*x %f%s", bitLength/4, value, value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
 
 func (b *boxedWriteBuffer) WriteString(logicalName string, bitLength uint32, value string, writerArgs ...WithWriterArgs) error {
 	additionalStringRepresentation := b.extractAdditionalStringRepresentation(UpcastWriterArgs(writerArgs...)...)
-	b.PushBack(b.asciiBoxWriter.BoxString(fmt.Sprintf("%s%s", value, additionalStringRepresentation), WithAsciiBoxName(logicalName)))
+	stringValue := fmt.Sprintf("%s%s", value, additionalStringRepresentation)
+	box := b.asciiBoxWriter.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(bitLength))))
+	b.PushBack(box)
 	b.move(uint(bitLength))
 	return nil
 }
@@ -232,20 +281,24 @@ func (b *boxedWriteBuffer) WriteVirtual(ctx context.Context, logicalName string,
 	var asciiBox AsciiBox
 	switch value.(type) {
 	case bool:
-		asciiBox = b.asciiBoxWriterLight.BoxString(fmt.Sprintf("%t", value), WithAsciiBoxName(logicalName))
+		stringValue := fmt.Sprintf("%t", value)
+		asciiBox = b.asciiBoxWriterLight.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(-1))))
 	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
-		asciiBox = b.asciiBoxWriterLight.BoxString(fmt.Sprintf("%#x %d%s", value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName))
+		stringValue := fmt.Sprintf("%#x %d%s", value, value, additionalStringRepresentation)
+		asciiBox = b.asciiBoxWriterLight.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(-1))))
 	case float32, float64:
-		asciiBox = b.asciiBoxWriterLight.BoxString(fmt.Sprintf("%x %f%s", value, value, additionalStringRepresentation), WithAsciiBoxName(logicalName))
+		stringValue := fmt.Sprintf("%x %f%s", value, value, additionalStringRepresentation)
+		asciiBox = b.asciiBoxWriterLight.BoxString(stringValue, WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(-1))))
 	case Serializable:
 		virtualBoxedWriteBuffer := NewWriteBufferBoxBasedWithOptions(b.mergeSingleBoxes, b.omitEmptyBoxes)
 		if err := value.(Serializable).SerializeWithWriteBuffer(ctx, virtualBoxedWriteBuffer); err == nil {
-			asciiBox = b.asciiBoxWriterLight.BoxBox(virtualBoxedWriteBuffer.GetBox(), WithAsciiBoxName(logicalName))
+			length := int(value.(LengthAware).GetLengthInBits(ctx))
+			asciiBox = b.asciiBoxWriterLight.BoxBox(virtualBoxedWriteBuffer.GetBox(), WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(length)))
 		} else {
-			b.asciiBoxWriterLight.BoxString(err.Error(), WithAsciiBoxName(logicalName))
+			b.asciiBoxWriterLight.BoxString(err.Error(), WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(-1))))
 		}
 	default:
-		asciiBox = b.asciiBoxWriterLight.BoxString(fmt.Sprintf("%v%s", value, additionalStringRepresentation), WithAsciiBoxName(logicalName))
+		asciiBox = b.asciiBoxWriterLight.BoxString(fmt.Sprintf("%v%s", value, additionalStringRepresentation), WithAsciiBoxName(logicalName), WithAsciiBoxFooter(b.getPosFooter(int(-1))))
 	}
 	b.PushBack(asciiBox)
 	return nil
@@ -308,3 +361,22 @@ func (b *boxedWriteBuffer) extractAdditionalStringRepresentation(readerWriterArg
 func (b *boxedWriteBuffer) move(bits uint) {
 	b.pos += bits
 }
+
+func (b *boxedWriteBuffer) getPosFooter(bitLength int) string {
+	if !b.printPosLengthFooter {
+		return ""
+	}
+	bytePos := int(b.pos) / 8
+	bitRemainder := int(b.pos) % 8
+	pos := strconv.Itoa(bytePos)
+	if bitRemainder != 0 {
+		pos += "," + strconv.Itoa(bitRemainder)
+	}
+	byteLength := bitLength / 8
+	bitLengthRemainder := bitLength % 8
+	length := strconv.Itoa(byteLength)
+	if bitLengthRemainder != 0 {
+		length += "," + strconv.Itoa(bitLengthRemainder)
+	}
+	return fmt.Sprintf("%s/%s", pos, length)
+}