mirror of https://github.com/anoshenko/rui.git
Changed ParseDataText function return values
This commit is contained in:
parent
3090a0e94f
commit
c3c8b9e858
|
@ -2,6 +2,7 @@
|
|||
|
||||
* Added support of binding
|
||||
* Added "binding" argument to CreateViewFromResources, CreateViewFromText, and CreateViewFromObject functions
|
||||
* Changed ParseDataText function return values
|
||||
|
||||
# v0.19.0
|
||||
|
||||
|
|
19
appServer.go
19
appServer.go
|
@ -164,7 +164,12 @@ func (app *application) postHandler(w http.ResponseWriter, req *http.Request) {
|
|||
DebugLog(message)
|
||||
}
|
||||
|
||||
if obj := ParseDataText(message); obj != nil {
|
||||
obj, err := ParseDataText(message)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var session Session = nil
|
||||
var response chan string = nil
|
||||
|
||||
|
@ -223,7 +228,6 @@ func (app *application) postHandler(w http.ResponseWriter, req *http.Request) {
|
|||
io.WriteString(w, <-response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (app *application) socketReader(bridge *wsBridge) {
|
||||
|
@ -241,9 +245,13 @@ func (app *application) socketReader(bridge *wsBridge) {
|
|||
DebugLog("🖥️ -> " + message)
|
||||
}
|
||||
|
||||
if obj := ParseDataText(message); obj != nil {
|
||||
command := obj.Tag()
|
||||
switch command {
|
||||
obj, err := ParseDataText(message)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
switch command := obj.Tag(); command {
|
||||
case "startSession":
|
||||
answer := ""
|
||||
if session, answer = app.startSession(obj, events, bridge, nil); session != nil {
|
||||
|
@ -295,7 +303,6 @@ func (app *application) socketReader(bridge *wsBridge) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sessionEventHandler(session Session, events chan DataObject, bridge bridge) {
|
||||
|
|
|
@ -78,6 +78,16 @@ func createBackground(obj DataObject) BackgroundElement {
|
|||
return result
|
||||
}
|
||||
|
||||
func parseBackgroundText(text string) BackgroundElement {
|
||||
obj, err := ParseDataText(text)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
return createBackground(obj)
|
||||
}
|
||||
|
||||
func parseBackgroundValue(value any) []BackgroundElement {
|
||||
|
||||
switch value := value.(type) {
|
||||
|
@ -96,15 +106,11 @@ func parseBackgroundValue(value any) []BackgroundElement {
|
|||
} else {
|
||||
return nil
|
||||
}
|
||||
} else if obj := ParseDataText(el.Value()); obj != nil {
|
||||
if element := createBackground(obj); element != nil {
|
||||
} else if element := parseBackgroundText(el.Value()); element != nil {
|
||||
background = append(background, element)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return background
|
||||
|
||||
|
@ -125,44 +131,34 @@ func parseBackgroundValue(value any) []BackgroundElement {
|
|||
return background
|
||||
|
||||
case string:
|
||||
if obj := ParseDataText(value); obj != nil {
|
||||
if element := createBackground(obj); element != nil {
|
||||
if element := parseBackgroundText(value); element != nil {
|
||||
return []BackgroundElement{element}
|
||||
}
|
||||
}
|
||||
|
||||
case []string:
|
||||
elements := make([]BackgroundElement, 0, len(value))
|
||||
for _, element := range value {
|
||||
if obj := ParseDataText(element); obj != nil {
|
||||
if element := createBackground(obj); element != nil {
|
||||
for _, text := range value {
|
||||
if element := parseBackgroundText(text); element != nil {
|
||||
elements = append(elements, element)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return elements
|
||||
|
||||
case []any:
|
||||
elements := make([]BackgroundElement, 0, len(value))
|
||||
for _, element := range value {
|
||||
switch element := element.(type) {
|
||||
for _, val := range value {
|
||||
switch val := val.(type) {
|
||||
case BackgroundElement:
|
||||
elements = append(elements, element)
|
||||
elements = append(elements, val)
|
||||
|
||||
case string:
|
||||
if obj := ParseDataText(element); obj != nil {
|
||||
if element := createBackground(obj); element != nil {
|
||||
if element := parseBackgroundText(val); element != nil {
|
||||
elements = append(elements, element)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
return nil
|
||||
|
|
|
@ -610,7 +610,10 @@ func borderSet(properties Properties, tag PropertyName, value any) []PropertyNam
|
|||
case Left, Right, Top, Bottom:
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if obj := ParseDataText(value); obj != nil {
|
||||
obj, err := ParseDataText(value)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
} else {
|
||||
return setSingleBorderObject(tag, obj)
|
||||
}
|
||||
|
||||
|
|
385
data.go
385
data.go
|
@ -1,6 +1,8 @@
|
|||
package rui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
@ -48,6 +50,9 @@ type DataObject interface {
|
|||
|
||||
// ToParams create a params(map) representation of a data object
|
||||
ToParams() Params
|
||||
|
||||
// PropertyByTag removes a data node corresponding to a property tag and returns it
|
||||
RemovePropertyByTag(tag string) DataNode
|
||||
}
|
||||
|
||||
// DataNodeType defines the type of DataNode
|
||||
|
@ -162,6 +167,28 @@ func (object *dataObject) PropertyByTag(tag string) DataNode {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (object *dataObject) RemovePropertyByTag(tag string) DataNode {
|
||||
if object.property != nil {
|
||||
for i, node := range object.property {
|
||||
if node.Tag() == tag {
|
||||
switch i {
|
||||
case 0:
|
||||
object.property = object.property[1:]
|
||||
|
||||
case len(object.property) - 1:
|
||||
object.property = object.property[:len(object.property)-1]
|
||||
|
||||
default:
|
||||
object.property = append(object.property[:i], object.property[i+1:]...)
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (object *dataObject) PropertyValue(tag string) (string, bool) {
|
||||
if node := object.PropertyByTag(tag); node != nil && node.Type() == TextNode {
|
||||
return node.Text(), true
|
||||
|
@ -318,54 +345,49 @@ func (node *dataNode) ArrayAsParams() []Params {
|
|||
return result
|
||||
}
|
||||
|
||||
// ParseDataText - parse text and return DataNode
|
||||
func ParseDataText(text string) DataObject {
|
||||
type dataParser struct {
|
||||
data []rune
|
||||
size int
|
||||
pos int
|
||||
line int
|
||||
lineStart int
|
||||
}
|
||||
|
||||
if strings.ContainsAny(text, "\r") {
|
||||
text = strings.ReplaceAll(text, "\r\n", "\n")
|
||||
text = strings.ReplaceAll(text, "\r", "\n")
|
||||
}
|
||||
data := append([]rune(text), rune(0))
|
||||
pos := 0
|
||||
size := len(data) - 1
|
||||
line := 1
|
||||
lineStart := 0
|
||||
|
||||
skipSpaces := func(skipNewLine bool) {
|
||||
for pos < size {
|
||||
switch data[pos] {
|
||||
func (parser *dataParser) skipSpaces(skipNewLine bool) {
|
||||
for parser.pos < parser.size {
|
||||
switch parser.data[parser.pos] {
|
||||
case '\n':
|
||||
if !skipNewLine {
|
||||
return
|
||||
}
|
||||
line++
|
||||
lineStart = pos + 1
|
||||
parser.line++
|
||||
parser.lineStart = parser.pos + 1
|
||||
|
||||
case '/':
|
||||
if pos+1 < size {
|
||||
switch data[pos+1] {
|
||||
if parser.pos+1 < parser.size {
|
||||
switch parser.data[parser.pos+1] {
|
||||
case '/':
|
||||
pos += 2
|
||||
for pos < size && data[pos] != '\n' {
|
||||
pos++
|
||||
parser.pos += 2
|
||||
for parser.pos < parser.size && parser.data[parser.pos] != '\n' {
|
||||
parser.pos++
|
||||
}
|
||||
pos--
|
||||
parser.pos--
|
||||
|
||||
case '*':
|
||||
pos += 3
|
||||
parser.pos += 3
|
||||
for {
|
||||
if pos >= size {
|
||||
if parser.pos >= parser.size {
|
||||
ErrorLog("Unexpected end of file")
|
||||
return
|
||||
}
|
||||
if data[pos-1] == '*' && data[pos] == '/' {
|
||||
if parser.data[parser.pos-1] == '*' && parser.data[parser.pos] == '/' {
|
||||
break
|
||||
}
|
||||
if data[pos-1] == '\n' {
|
||||
line++
|
||||
lineStart = pos
|
||||
if parser.data[parser.pos-1] == '\n' {
|
||||
parser.line++
|
||||
parser.lineStart = parser.pos
|
||||
}
|
||||
pos++
|
||||
parser.pos++
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -377,75 +399,72 @@ func ParseDataText(text string) DataObject {
|
|||
// do nothing
|
||||
|
||||
default:
|
||||
if !unicode.IsSpace(data[pos]) {
|
||||
if !unicode.IsSpace(parser.data[parser.pos]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
pos++
|
||||
}
|
||||
parser.pos++
|
||||
}
|
||||
}
|
||||
|
||||
parseTag := func() (string, bool) {
|
||||
skipSpaces(true)
|
||||
startPos := pos
|
||||
switch data[pos] {
|
||||
func (parser *dataParser) parseTag() (string, error) {
|
||||
parser.skipSpaces(true)
|
||||
startPos := parser.pos
|
||||
switch parser.data[parser.pos] {
|
||||
case '`':
|
||||
pos++
|
||||
parser.pos++
|
||||
startPos++
|
||||
for data[pos] != '`' {
|
||||
pos++
|
||||
if pos >= size {
|
||||
ErrorLog("Unexpected end of text")
|
||||
return string(data[startPos:size]), false
|
||||
for parser.data[parser.pos] != '`' {
|
||||
parser.pos++
|
||||
if parser.pos >= parser.size {
|
||||
return string(parser.data[startPos:parser.size]), errors.New("unexpected end of text")
|
||||
}
|
||||
}
|
||||
str := string(data[startPos:pos])
|
||||
pos++
|
||||
return str, true
|
||||
str := string(parser.data[startPos:parser.pos])
|
||||
parser.pos++
|
||||
return str, nil
|
||||
|
||||
case '\'', '"':
|
||||
stopSymbol := data[pos]
|
||||
pos++
|
||||
stopSymbol := parser.data[parser.pos]
|
||||
parser.pos++
|
||||
startPos++
|
||||
slash := false
|
||||
for stopSymbol != data[pos] {
|
||||
if data[pos] == '\\' {
|
||||
pos += 2
|
||||
for stopSymbol != parser.data[parser.pos] {
|
||||
if parser.data[parser.pos] == '\\' {
|
||||
parser.pos += 2
|
||||
slash = true
|
||||
} else {
|
||||
pos++
|
||||
parser.pos++
|
||||
}
|
||||
if pos >= size {
|
||||
ErrorLog("Unexpected end of text")
|
||||
return string(data[startPos:size]), false
|
||||
if parser.pos >= parser.size {
|
||||
return string(parser.data[startPos:parser.size]), errors.New("unexpected end of text")
|
||||
}
|
||||
}
|
||||
|
||||
if !slash {
|
||||
str := string(data[startPos:pos])
|
||||
pos++
|
||||
skipSpaces(false)
|
||||
return str, true
|
||||
str := string(parser.data[startPos:parser.pos])
|
||||
parser.pos++
|
||||
parser.skipSpaces(false)
|
||||
return str, nil
|
||||
}
|
||||
|
||||
buffer := make([]rune, pos-startPos+1)
|
||||
buffer := make([]rune, parser.pos-startPos+1)
|
||||
n1 := 0
|
||||
n2 := startPos
|
||||
|
||||
invalidEscape := func() (string, bool) {
|
||||
str := string(data[startPos:pos])
|
||||
pos++
|
||||
ErrorLogF("Invalid escape sequence in \"%s\" (position %d)", str, n2-2-startPos)
|
||||
return str, false
|
||||
invalidEscape := func() (string, error) {
|
||||
str := string(parser.data[startPos:parser.pos])
|
||||
parser.pos++
|
||||
return str, fmt.Errorf(`invalid escape sequence in "%s" (position %d)`, str, n2-2-startPos)
|
||||
}
|
||||
|
||||
for n2 < pos {
|
||||
if data[n2] != '\\' {
|
||||
buffer[n1] = data[n2]
|
||||
for n2 < parser.pos {
|
||||
if parser.data[n2] != '\\' {
|
||||
buffer[n1] = parser.data[n2]
|
||||
n2++
|
||||
} else {
|
||||
n2 += 2
|
||||
switch data[n2-1] {
|
||||
switch parser.data[n2-1] {
|
||||
case 'n':
|
||||
buffer[n1] = '\n'
|
||||
|
||||
|
@ -465,12 +484,12 @@ func ParseDataText(text string) DataObject {
|
|||
buffer[n1] = '\\'
|
||||
|
||||
case 'x', 'X':
|
||||
if n2+2 > pos {
|
||||
if n2+2 > parser.pos {
|
||||
return invalidEscape()
|
||||
}
|
||||
x := 0
|
||||
for range 2 {
|
||||
ch := data[n2]
|
||||
ch := parser.data[n2]
|
||||
if ch >= '0' && ch <= '9' {
|
||||
x = x*16 + int(ch-'0')
|
||||
} else if ch >= 'a' && ch <= 'f' {
|
||||
|
@ -485,12 +504,12 @@ func ParseDataText(text string) DataObject {
|
|||
buffer[n1] = rune(x)
|
||||
|
||||
case 'u', 'U':
|
||||
if n2+4 > pos {
|
||||
if n2+4 > parser.pos {
|
||||
return invalidEscape()
|
||||
}
|
||||
x := 0
|
||||
for range 4 {
|
||||
ch := data[n2]
|
||||
ch := parser.data[n2]
|
||||
if ch >= '0' && ch <= '9' {
|
||||
x = x*16 + int(ch-'0')
|
||||
} else if ch >= 'a' && ch <= 'f' {
|
||||
|
@ -505,90 +524,84 @@ func ParseDataText(text string) DataObject {
|
|||
buffer[n1] = rune(x)
|
||||
|
||||
default:
|
||||
str := string(data[startPos:pos])
|
||||
ErrorLogF("Invalid escape sequence in \"%s\" (position %d)", str, n2-2-startPos)
|
||||
return str, false
|
||||
str := string(parser.data[startPos:parser.pos])
|
||||
return str, fmt.Errorf(`invalid escape sequence in "%s" (position %d)`, str, n2-2-startPos)
|
||||
}
|
||||
}
|
||||
n1++
|
||||
}
|
||||
|
||||
pos++
|
||||
skipSpaces(false)
|
||||
return string(buffer[0:n1]), true
|
||||
parser.pos++
|
||||
parser.skipSpaces(false)
|
||||
return string(buffer[0:n1]), nil
|
||||
}
|
||||
|
||||
stopSymbol := func(symbol rune) bool {
|
||||
return unicode.IsSpace(symbol) ||
|
||||
slices.Contains([]rune{'=', '{', '}', '[', ']', ',', ' ', '\t', '\n', '\'', '"', '`', '/'}, symbol)
|
||||
for parser.pos < parser.size && !parser.stopSymbol(parser.data[parser.pos]) {
|
||||
parser.pos++
|
||||
}
|
||||
|
||||
for pos < size && !stopSymbol(data[pos]) {
|
||||
pos++
|
||||
}
|
||||
|
||||
endPos := pos
|
||||
skipSpaces(false)
|
||||
endPos := parser.pos
|
||||
parser.skipSpaces(false)
|
||||
if startPos == endPos {
|
||||
//ErrorLog("empty tag")
|
||||
return "", true
|
||||
}
|
||||
return string(data[startPos:endPos]), true
|
||||
return "", nil
|
||||
}
|
||||
return string(parser.data[startPos:endPos]), nil
|
||||
}
|
||||
|
||||
var parseObject func(tag string) DataObject
|
||||
var parseArray func() []DataValue
|
||||
func (parser *dataParser) stopSymbol(symbol rune) bool {
|
||||
return unicode.IsSpace(symbol) ||
|
||||
slices.Contains([]rune{'=', '{', '}', '[', ']', ',', ' ', '\t', '\n', '\'', '"', '`', '/'}, symbol)
|
||||
}
|
||||
|
||||
parseNode := func() DataNode {
|
||||
func (parser *dataParser) parseNode() (DataNode, error) {
|
||||
var tag string
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
if tag, ok = parseTag(); !ok {
|
||||
return nil
|
||||
if tag, err = parser.parseTag(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
skipSpaces(true)
|
||||
if data[pos] != '=' {
|
||||
ErrorLogF("expected '=' after a tag name (line: %d, position: %d)", line, pos-lineStart)
|
||||
return nil
|
||||
parser.skipSpaces(true)
|
||||
if parser.data[parser.pos] != '=' {
|
||||
return nil, fmt.Errorf("expected '=' after a tag name (line: %d, position: %d)", parser.line, parser.pos-parser.lineStart)
|
||||
}
|
||||
|
||||
pos++
|
||||
skipSpaces(true)
|
||||
switch data[pos] {
|
||||
parser.pos++
|
||||
parser.skipSpaces(true)
|
||||
switch parser.data[parser.pos] {
|
||||
case '[':
|
||||
node := new(dataNode)
|
||||
node.tag = tag
|
||||
|
||||
if node.array = parseArray(); node.array == nil {
|
||||
return nil
|
||||
if node.array, err = parser.parseArray(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return node
|
||||
return node, nil
|
||||
|
||||
case '{':
|
||||
node := new(dataNode)
|
||||
node.tag = tag
|
||||
if node.value = parseObject("_"); node.value == nil {
|
||||
return nil
|
||||
if node.value, err = parser.parseObject("_"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return node
|
||||
return node, nil
|
||||
|
||||
case '}', ']', '=':
|
||||
ErrorLogF("Expected '[', '{' or a tag name after '=' (line: %d, position: %d)", line, pos-lineStart)
|
||||
return nil
|
||||
return nil, fmt.Errorf(`expected '[', '{' or a tag name after '=' (line: %d, position: %d)`, parser.line, parser.pos-parser.lineStart)
|
||||
|
||||
default:
|
||||
var str string
|
||||
if str, ok = parseTag(); !ok {
|
||||
return nil
|
||||
if str, err = parser.parseTag(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node := new(dataNode)
|
||||
node.tag = tag
|
||||
|
||||
if data[pos] == '{' {
|
||||
if node.value = parseObject(str); node.value == nil {
|
||||
return nil
|
||||
if parser.data[parser.pos] == '{' {
|
||||
if node.value, err = parser.parseObject(str); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
val := new(dataStringValue)
|
||||
|
@ -596,91 +609,88 @@ func ParseDataText(text string) DataObject {
|
|||
node.value = val
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
}
|
||||
|
||||
parseObject = func(tag string) DataObject {
|
||||
if data[pos] != '{' {
|
||||
ErrorLogF("Expected '{' (line: %d, position: %d)", line, pos-lineStart)
|
||||
return nil
|
||||
func (parser *dataParser) parseObject(tag string) (DataObject, error) {
|
||||
if parser.data[parser.pos] != '{' {
|
||||
return nil, fmt.Errorf(`expected '{' (line: %d, position: %d)`, parser.line, parser.pos-parser.lineStart)
|
||||
}
|
||||
pos++
|
||||
parser.pos++
|
||||
|
||||
obj := new(dataObject)
|
||||
obj.tag = tag
|
||||
obj.property = []DataNode{}
|
||||
|
||||
for pos < size {
|
||||
var node DataNode
|
||||
|
||||
skipSpaces(true)
|
||||
if data[pos] == '}' {
|
||||
pos++
|
||||
skipSpaces(false)
|
||||
return obj
|
||||
for parser.pos < parser.size {
|
||||
parser.skipSpaces(true)
|
||||
if parser.data[parser.pos] == '}' {
|
||||
parser.pos++
|
||||
parser.skipSpaces(false)
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
if node = parseNode(); node == nil {
|
||||
return nil
|
||||
node, err := parser.parseNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj.property = append(obj.property, node)
|
||||
if data[pos] == '}' {
|
||||
pos++
|
||||
skipSpaces(true)
|
||||
return obj
|
||||
} else if data[pos] != ',' && data[pos] != '\n' {
|
||||
ErrorLogF(`Expected '}', '\n' or ',' (line: %d, position: %d)`, line, pos-lineStart)
|
||||
return nil
|
||||
if parser.data[parser.pos] == '}' {
|
||||
parser.pos++
|
||||
parser.skipSpaces(true)
|
||||
return obj, nil
|
||||
} else if parser.data[parser.pos] != ',' && parser.data[parser.pos] != '\n' {
|
||||
return nil, fmt.Errorf(`expected '}', '\n' or ',' (line: %d, position: %d)`, parser.line, parser.pos-parser.lineStart)
|
||||
}
|
||||
if data[pos] != '\n' {
|
||||
pos++
|
||||
|
||||
if parser.data[parser.pos] != '\n' {
|
||||
parser.pos++
|
||||
}
|
||||
skipSpaces(true)
|
||||
for data[pos] == ',' {
|
||||
pos++
|
||||
skipSpaces(true)
|
||||
|
||||
parser.skipSpaces(true)
|
||||
for parser.data[parser.pos] == ',' {
|
||||
parser.pos++
|
||||
parser.skipSpaces(true)
|
||||
}
|
||||
}
|
||||
|
||||
ErrorLog("Unexpected end of text")
|
||||
return nil
|
||||
}
|
||||
return nil, errors.New("unexpected end of text")
|
||||
}
|
||||
|
||||
parseArray = func() []DataValue {
|
||||
pos++
|
||||
skipSpaces(true)
|
||||
func (parser *dataParser) parseArray() ([]DataValue, error) {
|
||||
parser.pos++
|
||||
parser.skipSpaces(true)
|
||||
|
||||
array := []DataValue{}
|
||||
|
||||
for pos < size {
|
||||
var tag string
|
||||
var ok bool
|
||||
|
||||
skipSpaces(true)
|
||||
for data[pos] == ',' && pos < size {
|
||||
pos++
|
||||
skipSpaces(true)
|
||||
for parser.pos < parser.size {
|
||||
parser.skipSpaces(true)
|
||||
for parser.data[parser.pos] == ',' && parser.pos < parser.size {
|
||||
parser.pos++
|
||||
parser.skipSpaces(true)
|
||||
}
|
||||
|
||||
if pos >= size {
|
||||
if parser.pos >= parser.size {
|
||||
break
|
||||
}
|
||||
|
||||
if data[pos] == ']' {
|
||||
pos++
|
||||
skipSpaces(true)
|
||||
return array
|
||||
if parser.data[parser.pos] == ']' {
|
||||
parser.pos++
|
||||
parser.skipSpaces(true)
|
||||
return array, nil
|
||||
}
|
||||
|
||||
if tag, ok = parseTag(); !ok {
|
||||
return nil
|
||||
tag, err := parser.parseTag()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if data[pos] == '{' {
|
||||
obj := parseObject(tag)
|
||||
if obj == nil {
|
||||
return nil
|
||||
if parser.data[parser.pos] == '{' {
|
||||
obj, err := parser.parseObject(tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
array = append(array, obj)
|
||||
} else {
|
||||
|
@ -689,12 +699,11 @@ func ParseDataText(text string) DataObject {
|
|||
array = append(array, val)
|
||||
}
|
||||
|
||||
switch data[pos] {
|
||||
switch parser.data[parser.pos] {
|
||||
case ']', ',', '\n':
|
||||
|
||||
default:
|
||||
ErrorLogF("Expected ']' or ',' (line: %d, position: %d)", line, pos-lineStart)
|
||||
return nil
|
||||
return nil, fmt.Errorf(`expected ']' or ',' (line: %d, position: %d)`, parser.line, parser.pos-parser.lineStart)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -710,12 +719,28 @@ func ParseDataText(text string) DataObject {
|
|||
*/
|
||||
}
|
||||
|
||||
ErrorLog("Unexpected end of text")
|
||||
return nil
|
||||
return nil, errors.New("unexpected end of text")
|
||||
}
|
||||
|
||||
// ParseDataText - parse text and return DataNode
|
||||
func ParseDataText(text string) (DataObject, error) {
|
||||
|
||||
if strings.ContainsAny(text, "\r") {
|
||||
text = strings.ReplaceAll(text, "\r\n", "\n")
|
||||
text = strings.ReplaceAll(text, "\r", "\n")
|
||||
}
|
||||
|
||||
if tag, ok := parseTag(); ok {
|
||||
return parseObject(tag)
|
||||
parser := dataParser{
|
||||
data: append([]rune(text), rune(0)),
|
||||
pos: 0,
|
||||
line: 1,
|
||||
lineStart: 0,
|
||||
}
|
||||
return nil
|
||||
parser.size = len(parser.data) - 1
|
||||
|
||||
tag, err := parser.parseTag()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parser.parseObject(tag)
|
||||
}
|
||||
|
|
15
data_test.go
15
data_test.go
|
@ -6,10 +6,6 @@ import (
|
|||
|
||||
func TestParseDataText(t *testing.T) {
|
||||
|
||||
SetErrorLog(func(text string) {
|
||||
t.Error(text)
|
||||
})
|
||||
|
||||
text := `obj1 {
|
||||
key1 = val1,
|
||||
key2=obj2{
|
||||
|
@ -27,8 +23,10 @@ func TestParseDataText(t *testing.T) {
|
|||
key3 = "\n \t \\ \r \" ' \X4F\x4e \U01Ea",` +
|
||||
"key4=`" + `\n \t \\ \r \" ' \x8F \UF80a` + "`\r}"
|
||||
|
||||
obj := ParseDataText(text)
|
||||
if obj != nil {
|
||||
obj, err := ParseDataText(text)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if obj.Tag() != "obj1" {
|
||||
t.Error(`obj.Tag() != "obj1"`)
|
||||
}
|
||||
|
@ -173,9 +171,6 @@ func TestParseDataText(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
SetErrorLog(func(text string) {
|
||||
})
|
||||
|
||||
failText := []string{
|
||||
" ",
|
||||
"obj[]",
|
||||
|
@ -204,7 +199,7 @@ func TestParseDataText(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, txt := range failText {
|
||||
if obj := ParseDataText(txt); obj != nil {
|
||||
if _, err := ParseDataText(txt); err == nil {
|
||||
t.Errorf("result ParseDataText(\"%s\") must be fail", txt)
|
||||
}
|
||||
}
|
||||
|
|
19
popup.go
19
popup.go
|
@ -941,6 +941,25 @@ func NewPopup(view View, param Params) Popup {
|
|||
return popup
|
||||
}
|
||||
|
||||
/*
|
||||
func CreatePopupFromObject(session Session, object DataObject, binding any) Popup {
|
||||
node := object.RemovePropertyByTag(string(Content))
|
||||
if node == nil {
|
||||
ErrorLog(`"content" property not found`)
|
||||
return nil
|
||||
}
|
||||
|
||||
switch node.Type() {
|
||||
case ObjectNode:
|
||||
|
||||
case TextNode:
|
||||
|
||||
default:
|
||||
ErrorLog(`Unsupported data of "content" property`)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
*/
|
||||
// ShowPopup creates a new Popup and shows it
|
||||
func ShowPopup(view View, param Params) Popup {
|
||||
popup := NewPopup(view, param)
|
||||
|
|
|
@ -266,7 +266,8 @@ func (session *sessionData) setBridge(events chan DataObject, bridge bridge) {
|
|||
|
||||
func (session *sessionData) close() {
|
||||
if session.events != nil {
|
||||
session.events <- ParseDataText(`session-close{session="` + strconv.Itoa(session.sessionID) + `"}`)
|
||||
obj, _ := ParseDataText(`session-close{session="` + strconv.Itoa(session.sessionID) + `"}`)
|
||||
session.events <- obj
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,9 @@ func (resources *resourceManager) scanStringsDir(path string) {
|
|||
}
|
||||
|
||||
func loadStringResources(text string) {
|
||||
data := ParseDataText(text)
|
||||
if data == nil {
|
||||
data, err := ParseDataText(text)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
|
7
theme.go
7
theme.go
|
@ -686,8 +686,11 @@ func (theme *theme) addText(themeText string) bool {
|
|||
theme.init()
|
||||
}
|
||||
|
||||
data := ParseDataText(themeText)
|
||||
if data == nil || !data.IsObject() || data.Tag() != "theme" {
|
||||
data, err := ParseDataText(themeText)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return false
|
||||
} else if !data.IsObject() || data.Tag() != "theme" {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -398,7 +398,10 @@ func valueToTransformProperty(value any) TransformProperty {
|
|||
}
|
||||
|
||||
case string:
|
||||
if obj := ParseDataText(value); obj != nil {
|
||||
obj, err := ParseDataText(value)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
} else {
|
||||
return parseObject(obj)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,14 +117,17 @@ func CreateViewFromObject(session Session, object DataObject, binding any) View
|
|||
//
|
||||
// If the function fails, it returns nil and an error message is written to the log.
|
||||
func CreateViewFromText(session Session, text string, binding ...any) View {
|
||||
if data := ParseDataText(text); data != nil {
|
||||
data, err := ParseDataText(text)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
var b any = nil
|
||||
if len(binding) > 0 {
|
||||
b = binding[0]
|
||||
}
|
||||
return CreateViewFromObject(session, data, b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateViewFromResources create new View and initialize it by the content of
|
||||
|
@ -153,14 +156,20 @@ func CreateViewFromResources(session Session, name string, binding ...any) View
|
|||
|
||||
case viewDir:
|
||||
if data, err := fs.ReadFile(dir + "/" + name); err == nil {
|
||||
if data := ParseDataText(string(data)); data != nil {
|
||||
data, err := ParseDataText(string(data))
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
} else {
|
||||
return CreateViewFromObject(session, data, b)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
if data, err := fs.ReadFile(dir + "/" + viewDir + "/" + name); err == nil {
|
||||
if data := ParseDataText(string(data)); data != nil {
|
||||
data, err := ParseDataText(string(data))
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
} else {
|
||||
return CreateViewFromObject(session, data, b)
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +179,10 @@ func CreateViewFromResources(session Session, name string, binding ...any) View
|
|||
|
||||
if resources.path != "" {
|
||||
if data, err := os.ReadFile(resources.path + viewDir + "/" + name); err == nil {
|
||||
if data := ParseDataText(string(data)); data != nil {
|
||||
data, err := ParseDataText(string(data))
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
} else {
|
||||
return CreateViewFromObject(session, data, b)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,13 +173,11 @@ func (container *viewsContainerData) htmlSubviews(self View, buffer *strings.Bui
|
|||
}
|
||||
|
||||
func viewFromTextValue(text string, session Session) View {
|
||||
if strings.Contains(text, "{") && strings.Contains(text, "}") {
|
||||
if data := ParseDataText(text); data != nil {
|
||||
if data, err := ParseDataText(text); err == nil {
|
||||
if view := CreateViewFromObject(session, data, nil); view != nil {
|
||||
return view
|
||||
}
|
||||
}
|
||||
}
|
||||
return NewTextView(session, Params{Text: text})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue