LCOV - code coverage report
Current view: top level - legacy/ascend950/framework/topo/topo_addr_info/src - xml_parser.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.3 % 116 99
Test Date: 2026-08-18 17:47:01 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "xml_parser.h"
      12              : 
      13              : #include <ctype.h>
      14              : #include <stdio.h>
      15              : #include <string.h>
      16              : #include <sys/stat.h>
      17              : 
      18              : #include "securec.h"
      19              : #include "topo_addr_info_log.h"
      20              : 
      21              : #define MAX_LINE_LEN 4096
      22              : 
      23              : /* ─── 工具函数 ─── */
      24              : 
      25         2805 : const char* TagFindAttr(const TagEntry* e, const char* name)
      26              : {
      27         2805 :     for (int i = 0; i < e->attrCount; i++) {
      28         2803 :         if (strcmp(e->attrs[i].name, name) == 0) {
      29         2803 :             return e->attrs[i].value;
      30              :         }
      31              :     }
      32            2 :     return NULL;
      33              : }
      34              : 
      35         4586 : static bool IsSelfClose(const char* tag, const char* tagEnd)
      36              : {
      37         4586 :     size_t n = (size_t)(tagEnd - tag + 1);
      38         4586 :     return n >= 2 && tag[n - 2] == '/';
      39              : }
      40              : 
      41         4587 : static void GetTagName(const char* tag, char* name, size_t len)
      42              : {
      43         4587 :     if (name == NULL || len == 0) {
      44            0 :         return;
      45              :     }
      46              : 
      47         4587 :     const char* p = tag + 1;
      48         4587 :     if (*p == '/') {
      49            0 :         p++;
      50              :     }
      51         4587 :     const char* start = p;
      52        19066 :     while (*p != '\0' && *p != ' ' && *p != '>' && *p != '/') {
      53        14479 :         p++;
      54              :     }
      55         4587 :     size_t n = (size_t)(p - start);
      56         4587 :     if (n >= len) {
      57            0 :         n = len - 1;
      58              :     }
      59         4587 :     if (strncpy_s(name, len, start, n) != 0) {
      60            0 :         name[0] = '\0';
      61            0 :         return;
      62              :     }
      63         4587 :     name[n] = '\0';
      64              : }
      65              : 
      66         4586 : static void ExtractAttrs(const char* tag, TagEntry* e)
      67              : {
      68         4586 :     int ac = e->attrCount;
      69         4586 :     const char* scan = tag;
      70              : 
      71         8568 :     while (ac < MAX_ATTRS_PER_TAG) {
      72         8568 :         scan = strchr(scan, ' ');
      73         8568 :         if (scan == NULL) {
      74         4200 :             break;
      75              :         }
      76         4368 :         scan++;
      77         4368 :         if (*scan == '\0') {
      78            0 :             break;
      79              :         }
      80         4368 :         const char* eq = strchr(scan, '=');
      81         4368 :         if (eq == NULL || eq <= scan) {
      82              :             break;
      83              :         }
      84         3983 :         size_t nlen = (size_t)(eq - scan);
      85         3983 :         if (nlen >= MAX_ATTR_NAME_LEN) {
      86            0 :             nlen = MAX_ATTR_NAME_LEN - 1;
      87              :         }
      88         3983 :         (void)strncpy_s(e->attrs[ac].name, sizeof(e->attrs[ac].name), scan, nlen);
      89              : 
      90         3983 :         const char* vq = strchr(eq, '\"');
      91         3983 :         if (vq == NULL) {
      92            1 :             break;
      93              :         }
      94         3982 :         vq++;
      95         3982 :         const char* ve = strchr(vq, '\"');
      96         3982 :         if (ve == NULL) {
      97            0 :             break;
      98              :         }
      99         3982 :         size_t vlen = (size_t)(ve - vq);
     100         3982 :         if (vlen >= MAX_ATTR_VAL_LEN) {
     101            0 :             vlen = MAX_ATTR_VAL_LEN - 1;
     102              :         }
     103         3982 :         (void)strncpy_s(e->attrs[ac].value, sizeof(e->attrs[ac].value), vq, vlen);
     104              : 
     105         3982 :         ac++;
     106         3982 :         scan = ve + 1;
     107              :     }
     108         4586 :     e->attrCount = ac;
     109         4586 : }
     110              : 
     111              : /* ─── 内部辅助:处理一个开标签 ─── */
     112              : /* 返回 tagEnd+1(下一位置),通过指针更新 cnt / dc */
     113         4587 : static char* HandleOpenTag(char* t, char* tagEnd, TagEntry* tags, unsigned int maxTags, unsigned int* cnt, int* dc)
     114              : {
     115              :     char name[MAX_TAG_NAME_LEN];
     116         4587 :     GetTagName(t, name, sizeof(name));
     117         4587 :     if (name[0] == '\0') {
     118            1 :         return tagEnd + 1;
     119              :     }
     120              : 
     121         4586 :     bool selfClose = IsSelfClose(t, tagEnd);
     122         4586 :     if (*cnt < maxTags) {
     123         4586 :         TagEntry* e = &tags[*cnt];
     124         4586 :         (void)memset_s(e, sizeof(*e), 0, sizeof(*e));
     125         4586 :         if (strcpy_s(e->tagName, sizeof(e->tagName), name) != 0) {
     126            0 :             TOPO_ERR("HandleOpenTag: strcpy_s failed, name=%s", name);
     127            0 :             return NULL;
     128              :         }
     129         4586 :         e->isSelfClose = selfClose;
     130         4586 :         e->depth = *dc;
     131         4586 :         ExtractAttrs(t, e);
     132         4586 :         (*cnt)++;
     133              :     }
     134              : 
     135         4586 :     if (!selfClose) {
     136         2021 :         (*dc)++;
     137              :     }
     138         4586 :     return tagEnd + 1;
     139              : }
     140              : 
     141              : /* ─── 逐行解析 XML,识别标签 ─── */
     142              : /* 逐行解析 XML,识别标签 */
     143          384 : static TopoAddrResult ParseXmlLines(FILE* fp, TagEntry* tags, unsigned int maxTags, unsigned int* cnt)
     144              : {
     145          384 :     int dc = 0;
     146              :     char line[MAX_LINE_LEN];
     147         6354 :     while (fgets(line, sizeof(line), fp) != NULL) {
     148         5970 :         char* t = line;
     149        12580 :         while (*t != '\0') {
     150        18780 :             while (*t != '\0' && isspace((unsigned char)*t)) {
     151         6200 :                 t++;
     152              :             }
     153        12580 :             if (*t == '\0' || strncmp(t, "<!--", 4) == 0) {
     154              :                 break;
     155              :             }
     156              : 
     157         6611 :             char* tagEnd = strchr(t, '>');
     158         6611 :             if (tagEnd == NULL) {
     159            1 :                 break;
     160              :             }
     161              : 
     162         6610 :             if (t[0] == '<' && t[1] == '/') {
     163         2023 :                 if (dc > 0) {
     164         2021 :                     dc--;
     165              :                 }
     166         2023 :                 t = tagEnd + 1;
     167         2023 :                 continue;
     168              :             }
     169              : 
     170         4587 :             if (t[0] == '<') {
     171         4587 :                 t = HandleOpenTag(t, tagEnd, tags, maxTags, cnt, &dc);
     172         4587 :                 if (t == NULL) {
     173            0 :                     return TOPO_ERR_INTERNAL;
     174              :                 }
     175         4587 :                 continue;
     176              :             }
     177            0 :             break;
     178              :         }
     179              :     }
     180          384 :     return TOPO_SUCCESS;
     181              : }
     182              : 
     183              : /* ─── 核心解析函数 ─── */
     184              : 
     185          396 : TopoAddrResult ParseXmlTags(const char* xmlPath, TagEntry* tags, unsigned int* tagCount, unsigned int maxTags)
     186              : {
     187          396 :     *tagCount = 0;
     188              : 
     189          396 :     FILE* fp = fopen(xmlPath, "rb");
     190          396 :     if (fp == NULL) {
     191           11 :         TOPO_INFO("ParseXmlTags: cannot open %s", xmlPath);
     192           11 :         return TOPO_ERR_OPEN_FILE;
     193              :     }
     194              : 
     195              :     struct stat st;
     196          385 :     if (fstat(fileno(fp), &st) != 0 || st.st_size == 0) {
     197            1 :         TOPO_ERR("ParseXmlTags: stat failed or empty file, path=%s", xmlPath);
     198            1 :         fclose(fp);
     199            1 :         return TOPO_ERR_OPEN_FILE;
     200              :     }
     201              : 
     202          384 :     unsigned int cnt = 0;
     203          384 :     if (ParseXmlLines(fp, tags, maxTags, &cnt) != TOPO_SUCCESS) {
     204            0 :         fclose(fp);
     205            0 :         return TOPO_ERR_INTERNAL;
     206              :     }
     207              : 
     208          384 :     fclose(fp);
     209          384 :     *tagCount = cnt;
     210          384 :     if (cnt == 0) {
     211            0 :         TOPO_ERR("ParseXmlTags: no valid tags found in %s", xmlPath);
     212            0 :         return TOPO_ERR_NOT_FOUND;
     213              :     }
     214          384 :     return TOPO_SUCCESS;
     215              : }
        

Generated by: LCOV version 2.0-1