• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16const { NapiLog } = require("./NapiLog");
17const re = require("./re")
18
19var DataType = {
20    INT8: 1,
21    INT16: 2,
22    INT32: 3,
23    INT64: 4,
24    STRING: 5,
25    NODE: 6,
26    ATTR: 7,//Attribute definition
27    ARRAY: 8,
28    REFERENCE: 9,//Reference a = &b
29    DELETE: 10,//Attribute deletion a = delete
30    BOOL: 11,
31}
32var NodeType = {
33    DATA: 0,
34    COPY: 1,//Copy a : b {}
35    REFERENCE: 2,//Reference a : &b {}
36    DELETE: 3,//Deletion class nodes a : delete {}
37    TEMPLETE: 4,//Templete Class nodes templete a {}
38    INHERIT: 5,//Data class nodes, inherit a :: b {}
39}
40
41class NodeTools {
42}
43
44function getRoot(node) {
45    while (node.parent_ != undefined)
46        node = node.parent_
47    return node;
48}
49
50NodeTools.isElders = function (node, elders) {
51    while (node != undefined) {
52        if (node == elders) {
53            return true;
54        }
55        node = node.parent_
56    }
57    return false;
58}
59
60NodeTools.getPathByNode = function (node) {
61    if (node == null) return "";
62    let ret = node.name_;
63    while (node.parent_ != undefined) {
64        node = node.parent_;
65        if (node.nodeType_ == NodeType.REFERENCE) {
66            node = NodeTools.getNodeByPath(getRoot(node), node.ref_);
67        }
68        ret = node.name_ + "." + ret;
69    }
70    return ret;
71}
72NodeTools.getNodeByPath = function (node, path) {
73    let ps = path.split(".")
74    if (ps[0] == "root") ps.shift()
75    for (let p in ps) {
76        node = NodeTools.findChildByName(node, ps[p])
77        if (node == null) return null;
78    }
79    return node;
80}
81
82NodeTools.lookupInherit = function (node) {
83    if (node.type_ == DataType.NODE && node.nodeType_ == NodeType.INHERIT &&
84         node.parent_.nodeType_ == NodeType.INHERIT) {
85        let p = NodeTools.lookupInherit(node.parent_);
86        if (p == null) return p;
87        return NodeTools.findChildByName(p, node.ref_);
88    }
89    return NodeTools.findChildByName(node.parent_, node.ref_);
90}
91
92NodeTools.lookup = function (node) {//copy,reference,inherit
93    let refname;
94    if (node.type_ == DataType.NODE &&
95        (node.nodeType_ == NodeType.COPY ||
96            node.nodeType_ == NodeType.REFERENCE ||
97            node.nodeType_ == NodeType.INHERIT))
98        refname = node.ref_;
99    else if (node.type_ == DataType.ATTR &&
100        node.value_.type_ == DataType.REFERENCE)
101        refname = node.value_.value_;
102    else return null;
103    if (refname.indexOf(".") >= 0) return NodeTools.getNodeByPath(getRoot(node), refname);
104
105    let ret = NodeTools.findChildByName(node.parent_, refname);
106    if (ret == null) {
107        if (node.type_ == DataType.NODE && node.nodeType_ == NodeType.INHERIT &&
108             node.parent_.nodeType_ == NodeType.INHERIT) {
109            ret = NodeTools.lookupInherit(node);
110        }
111    }
112    return ret;
113}
114
115NodeTools.recursionNode = function (node, callback) {//Find all nodes
116    if (node.type_ == DataType.NODE) {
117        callback(node)
118        for (let n in node.value_) {
119            NodeTools.recursionNode(node.value_[n], callback)
120        }
121    }
122}
123NodeTools.recursionAll = function (node, callback, isForward) {
124    let ret = false;
125    if (isForward) ret = callback(node)
126    if (node.type_ == DataType.NODE) {
127        for (let i = 0; i < node.value_.length; i++) {
128            if (NodeTools.recursionAll(node.value_[i], callback, isForward))
129                i--;
130        }
131    }
132    if (!isForward) ret = callback(node)
133    return ret;
134}
135NodeTools.redefineCheck = function (node) {
136    let ret = true;
137    NodeTools.recursionNode(node, (pn) => {
138        let nameMap = [];
139        for (let i in pn.value_) {
140            if (nameMap.indexOf(pn.value_[i].name_) >= 0) {
141                pn.value_[i].errMsg_ = "重名:"+pn.value_[i].lineno_;
142                ret = false;
143            }
144            else {
145                nameMap.push(pn.value_[i].name_)
146                pn.value_[i].errMsg_ = null;
147            }
148        }
149    })
150    return ret;
151}
152function separate(node) {
153    let pn = node.parent_;
154    if (pn == null)
155        return;
156    for (let i in pn.value_) {
157        if (pn.value_[i] == node) {
158            pn.value_.splice(i, 1);
159        }
160    }
161}
162NodeTools.findChildByName = function (node, name) {
163    for (let i in node.value_) {
164        if (node.value_[i].name_ == name) {
165            return node.value_[i]
166        }
167    }
168    return null;
169}
170
171NodeTools.copyNode = function (node, parent) {
172    let ret = {
173        type_: node.type_,
174        name_: node.name_,
175        lineno_: node.lineno_,
176        parent_: parent
177    }; if (node.raw_ != undefined)
178        ret.raw_ = node.raw_
179    switch (node.type_) {
180        case DataType.INT8:
181        case DataType.INT16:
182        case DataType.INT32:
183        case DataType.INT64:
184            ret.value_ = node.value_
185            ret.jinzhi_ = node.jinzhi_
186            break;
187        case 5://string
188            ret.value_ = node.value_;
189            break;
190        case 6://ConfigNode
191            ret.nodeType_ = node.nodeType_;
192            if ([NodeType.INHERIT, NodeType.COPY, NodeType.REFERENCE].indexOf(node.nodeType_) > -1) {
193                ret.ref_ = node.ref_;
194            } else if (!([NodeType.DATA, NodeType.TEMPLETE, NodeType.DELETE].indexOf(node.nodeType_) > -1)) {
195                NapiLog.logError("unknow node type:"+ret.lineno_);
196            }
197            ret.value_ = []
198            for (let i in node.value_) { ret.value_.push(NodeTools.copyNode(node.value_[i], ret)) }
199            break;
200        case 7://ConfigTerm
201            ret.value_ = NodeTools.copyNode(node.value_, ret)
202            break;
203        case 8://array Array class attribute value
204            ret.value_ = []
205            for (let i in node.value_) { ret.value_.push(NodeTools.copyNode(node.value_[i], ret)) }
206            break;
207        case 9://Attribute equal to leaf
208            ret.value_ = node.value_;
209            break;
210        case 10://Delete attribute
211            ret.value_ = null;
212            break;
213        case 11://bool
214            ret.value_ = node.value_
215            break;
216        default:
217            NapiLog.logInfo("unknow", node.type_)
218            break;
219    }return ret;
220}
221
222function makeError(node, errStr) {
223    if (node.raw_ != undefined) {
224        node.raw_.errMsg_ = errStr;
225    }
226}
227NodeTools.nodeNestCheck = function (node) {
228    NodeTools.recursionAll(node, (pn) => {
229        if (pn.type_ == DataType.NODE) {
230            if (pn.nodeType_ == NodeType.COPY && pn.raw_.errMsg_ == null) {
231                pn.raw_.errMsg_ = "有Copy的嵌套"+pn.raw_.lineno_;
232            }
233        }
234        return false;
235    }, false);
236}
237NodeTools.recursionCopyAndReferenceNodes = function (pn) {
238    let ref = NodeTools.lookup(pn);
239    if (ref == null) {
240        NapiLog.logError("reference not exist" + NodeTools.getPathByNode(pn) + ":" + pn.ref_);
241        if (pn.nodeType_ == NodeType.COPY) makeError(pn, "复制目标没找到:"+pn.lineno_)
242        else makeError(pn, "引用目标没找到:"+pn.lineno_)
243        return false;
244    } else if (ref.nodeType_ == NodeType.TEMPLETE) {
245        if (pn.nodeType_ == NodeType.COPY) makeError(pn, "复制目标不能为模板节点:"+pn.lineno_)
246        else makeError(pn, "引用目标不能为模板节点:"+pn.lineno_)
247        return false;
248    } else if (ref.nodeType_ == NodeType.DELETE) {
249        if (pn.nodeType_ == NodeType.COPY) makeError(pn, "复制目标不能为删除节点:"+pn.lineno_)
250        else makeError(pn, "引用目标不能为删除节点:"+pn.lineno_)
251        return false;
252    } else if (NodeTools.isElders(pn, ref)) {
253        NapiLog.logError("circular reference" + NodeTools.getPathByNode(pn) + ":" + pn.ref_);
254        if (pn.nodeType_ == NodeType.COPY) {
255            makeError(pn, "循环复制:"+pn.lineno_)
256        } else {
257            makeError(pn, "循环引用:"+pn.lineno_)
258        }
259        return false;
260    } else if (pn.nodeType_ == NodeType.COPY) {
261        if (ref.nodeType_ == NodeType.COPY) {
262            pn.raw_.errMsg_ = "有Copy的嵌套:"+pn.raw_.lineno_;
263        }
264        pn.nodeType_ = NodeType.DATA;//Convert current node to data class node
265        let tref = NodeTools.copyNode(ref, pn.parent_);//Copy a Ref
266        tref.name_ = pn.name_;
267        NodeTools.merge(tref, pn)//Merge the contents of the current node
268        pn.value_ = tref.value_;
269        return false;
270    } else if (pn.nodeType_ == NodeType.REFERENCE) {
271        pn.nodeType_ = ref.nodeType_; pn.name_ = ref.name_;
272        NodeTools.merge(ref, pn)//Merge the contents of the current node into Ref
273        separate(pn);
274        return true;
275    }
276    return false;
277}
278
279NodeTools.checkInheritNode = function (pn) {
280    let ref = NodeTools.lookup(pn);
281    if (ref == null) {
282        makeError(pn, "找不到继承目标:"+pn.lineno_)
283    } else if (ref.type_ != DataType.NODE) {
284        makeError(pn, "不能继承属性:"+pn.lineno_)
285    } else if (ref.nodeType_ == NodeType.REFERENCE) {
286        makeError(pn, "不能继承引用类节点:"+pn.lineno_)
287    } else if (ref.nodeType_ == NodeType.DELETE) {
288        makeError(pn, "不能继承删除类节点:"+pn.lineno_)
289    } else if (ref.nodeType_ == NodeType.DATA) {
290        makeError(pn, "不能继承数据类节点:"+pn.lineno_)
291    } else if (ref.nodeType_ == NodeType.INHERIT) {
292        makeError(pn, "不能继承继承类节点:"+pn.lineno_)
293    } else if (ref.nodeType_ == NodeType.COPY) {
294        makeError(pn, "不能继承复制类节点:"+pn.lineno_)
295    }
296}
297
298NodeTools.nodeExpand = function (node) {
299    NodeTools.recursionAll(node, (pn) => {
300        if (pn.type_ == DataType.NODE) {
301            if (pn.nodeType_ == NodeType.DELETE) {
302                separate(pn);
303                return true;
304            } if (pn.nodeType_ == NodeType.COPY || pn.nodeType_ == NodeType.REFERENCE) {
305                return NodeTools.recursionCopyAndReferenceNodes(pn);
306            } if (pn.nodeType_ == NodeType.INHERIT) {
307                NodeTools.checkInheritNode(pn);
308            }
309        }
310        else if (pn.type_ == DataType.ATTR) {
311            if (pn.value_.type_ == DataType.DELETE) {
312                separate(pn);
313                return true;
314            } if (pn.value_.type_ == DataType.REFERENCE) {
315                let ref = NodeTools.lookup(pn);
316                if (ref == null || ref.type_ != DataType.NODE || ref.nodeType_ == NodeType.REFERENCE ||
317                    ref.nodeType_ == NodeType.TEMPLETE || ref.nodeType_ == NodeType.DELETE) {
318                    NapiLog.logError("reference invalid node" + NodeTools.getPathByNode(pn) + ":" + pn.value_.value_);
319                    if (ref == null) makeError(pn, "找不到引用目标:"+pn.lineno_)
320                    else if (ref.type_ != DataType.NODE) makeError(pn, "不能引用属性:"+pn.lineno_)
321                    else if (ref.nodeType_ == NodeType.REFERENCE) makeError(pn, "不能引用引用类节点:"+pn.lineno_)
322                    else if (ref.nodeType_ == NodeType.TEMPLETE) makeError(pn, "不能引用模板类节点:"+pn.lineno_)
323                    else if (ref.nodeType_ == NodeType.DELETE) makeError(pn, "不能引用删除类节点:"+pn.lineno_)
324                } else {
325                    pn.refNode_ = ref;
326                }
327            }
328        }
329        return false;
330    }, false);
331}
332
333NodeTools.inheritExpand = function (node) {
334    NodeTools.recursionAll(node, (pn) => {
335        let tt = re.match("^[a-zA-Z_]{1}[a-zA-Z_0-9]*$", pn.name_);
336        if (tt == null) {
337            makeError(pn, "名字不合规范:"+pn.lineno_)
338        }
339        if (pn.type_ != DataType.NODE) return false;
340        if (pn.nodeType_ != NodeType.INHERIT) return false;
341        let inherit = NodeTools.lookup(pn);
342        if (inherit == null) {
343            NapiLog.logError("inherit invalid node: " + NodeTools.getPathByNode(pn) + ":" + pn.ref_);
344            makeError(pn, "找不到继承目标:"+pn.lineno_)
345            return false;
346        }
347        pn.nodeType_ = NodeType.DATA;
348        let tinherit = NodeTools.copyNode(inherit, pn.parent_);
349        NodeTools.merge(tinherit, pn)
350        pn.value_ = tinherit.value_
351        return false;
352    }, true);
353}
354NodeTools.merge = function (node1, node2) {
355    if (node2 == null) {
356        return true;
357    }
358    if (node2.raw_ == undefined)
359        node1.raw_ = node2
360    else
361        node1.raw_ = node2.raw_
362    if (node1.type_ == DataType.NODE) {
363
364        if (node1.name_ != node2.name_) {
365            return false;
366        }
367        node1.nodeType_ = node2.nodeType_;
368        if (node2.nodeType_ == NodeType.INHERIT || node2.nodeType_ == NodeType.REFERENCE
369            || node2.nodeType_ == NodeType.COPY) node1.ref_ = node2.ref_
370        if (node1.value_ == undefined) node1.value_ = [];
371
372        for (let i in node2.value_) {
373            let child2 = node2.value_[i];
374            let child1 = NodeTools.findChildByName(node1, child2.name_)
375            if (child1 == null) {
376                child1 = {
377                    type_: child2.type_,
378                    name_: child2.name_,
379                    lineno_: child2.lineno_,
380                    parent_: node1
381                }
382                node1.value_.push(child1)
383            }
384            else if (child1.type_ != child2.type_) {
385                child2.raw_.errMsg_ = "所修改的子节的类型和父节点类型不同:"+child2.raw_.lineno_;
386                return false;
387            }
388            NodeTools.merge(child1, child2);
389        }
390    }
391    else if (node1.type_ == DataType.ATTR) {
392        node1.value_ = NodeTools.copyNode(node2.value_, node1)
393    }
394    return true;
395}
396NodeTools.jinZhi10ToX = function (num, jinzhi) {
397    let ret;
398    switch (jinzhi) {
399        case 2:
400            ret = "0b"
401            break;
402        case 8:
403            ret = "0"
404            break;
405        case 10:
406            ret = ""
407            break;
408        case 16:
409            ret = "0x"
410            break;
411        default:
412            NapiLog.logError(jinzhi + "进制转换失败")
413            break;
414    }
415    return ret + num.toString(jinzhi);
416}
417NodeTools.jinZhiXTo10 = function (s) {
418    if (s == null || s.length == 0)
419        return [0, 10]
420    if (s[0] == '0') {
421        if (s.length == 1) {
422            return [parseInt(s, 10), 10];
423        }
424        else if (s[1] == 'b') {
425            return [parseInt(s.substring(2), 2), 2];
426        }
427        else if (s[1] == 'x' || s[1] == 'X') {
428            return [parseInt(s.substring(2), 16), 16];
429        }
430        else {
431            return [parseInt(s.substring(1), 8), 8];
432        }
433    }
434    else {
435        return [parseInt(s, 10), 10];
436    }
437}
438
439NodeTools.createNewNode = function (type, name, value, nodetype) {
440    let ret = new Object();
441    ret.type_ = type;
442    ret.name_ = name;
443    ret.value_ = value;
444    if (type < DataType.STRING) ret.jinzhi_ = 10;
445    if (type == DataType.NODE) ret.nodeType_ = nodetype;
446    return ret;
447}
448NodeTools.arrayToString = function (node, maxw) {
449    let ret = ""
450    let type = DataType.INT8;
451    for (let d in node.value_) {
452        if (type < node.value_[d].type_) type = node.value_[d].type_;
453    }
454    let line = ""
455    for (let d in node.value_) {
456        if (d > 0) {
457            line += ","
458            if (maxw != undefined) {
459                if (line.length >= maxw) {
460                    ret += line + "\n";
461                    line = "";
462                }
463            }
464        }
465        if (type == DataType.STRING)
466            line += '"' + node.value_[d].value_ + '"';
467        else
468            line += NodeTools.jinZhi10ToX(node.value_[d].value_, node.value_[d].jinzhi_);
469    }
470    ret += line;
471    return ret;
472}
473
474NodeTools.stringToArray = function (s) {
475    let type = DataType.INT8;
476    let ret = [];
477    s = s.replace(/\n/g, "")
478    if (s.length <= 0)
479        return ret;
480    if (s.indexOf('"') >= 0) {
481        type = DataType.STRING;
482        let p = 0;
483        let stat = 0;
484        let v
485        while (p < s.length && stat < 100) {
486            switch (stat) {
487                case 0:
488                    if (s[p] == '"') {
489                        stat = 1; v = "";
490                    }
491                    else if (s[p] != ' ') stat = 100;
492                    break;
493                case 1:
494                    if (s[p] == '"') {
495                        stat = 2;
496                        ret.push(NodeTools.createNewNode(type, "", v))
497                    }
498                    else v += s[p]
499                    break;
500                case 2:
501                    if (s[p] == ',') stat = 0;
502                    else if (s[p] != ' ') stat = 100;
503                    break;
504            }
505            p += 1;
506        }
507    } else {
508        let arr = s.split(",");
509        stringToArrayWithQuote(ret, type, arr);
510    } return ret;
511}
512
513function stringToArrayWithQuote(ret, type, arr) {
514    for (let i in arr) {
515        let num = NodeTools.jinZhiXTo10(arr[i])
516        if (isNaN(num[0])) num[0] = 0;
517        let attr = NodeTools.createNewNode(type, "", num[0]);
518        attr.jinzhi_ = num[1]
519        ret.push(attr)
520        if (num[0] <= 0xff) {
521            if (type < DataType.INT8) type = DataType.INT8;
522        }
523        else if (num[0] <= 0xffff) {
524            if (type < DataType.INT16) type = DataType.INT16;
525        }
526        else if (num[0] <= 0xffffffff) {
527            if (type < DataType.INT32) type = DataType.INT32;
528        }
529        else {
530            type = DataType.INT64;
531        }
532    }
533    if (type != DataType.INT8) {
534        for (let i in ret) {
535            ret[i].type_ = type;
536        }
537    }
538}
539
540module.exports = {
541    NodeTools,
542    DataType,
543    NodeType
544}