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}