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-04 10:52:23 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,
     114              :     unsigned int *cnt, int *dc)
     115              : {
     116              :     char name[MAX_TAG_NAME_LEN];
     117         4587 :     GetTagName(t, name, sizeof(name));
     118         4587 :     if (name[0] == '\0') {
     119            1 :         return tagEnd + 1;
     120              :     }
     121              : 
     122         4586 :     bool selfClose = IsSelfClose(t, tagEnd);
     123         4586 :     if (*cnt < maxTags) {
     124         4586 :         TagEntry *e = &tags[*cnt];
     125         4586 :         (void)memset_s(e, sizeof(*e), 0, sizeof(*e));
     126         4586 :         if (strcpy_s(e->tagName, sizeof(e->tagName), name) != 0) {
     127            0 :             TOPO_ERR("HandleOpenTag: strcpy_s failed, name=%s", name);
     128            0 :             return NULL;
     129              :         }
     130         4586 :         e->isSelfClose = selfClose;
     131         4586 :         e->depth = *dc;
     132         4586 :         ExtractAttrs(t, e);
     133         4586 :         (*cnt)++;
     134              :     }
     135              : 
     136         4586 :     if (!selfClose) {
     137         2021 :         (*dc)++;
     138              :     }
     139         4586 :     return tagEnd + 1;
     140              : }
     141              : 
     142              : /* ─── 逐行解析 XML,识别标签 ─── */
     143              : /* 逐行解析 XML,识别标签 */
     144          384 : static TopoAddrResult ParseXmlLines(FILE *fp, TagEntry *tags, unsigned int maxTags,
     145              :                                     unsigned int *cnt)
     146              : {
     147          384 :     int dc = 0;
     148              :     char line[MAX_LINE_LEN];
     149         6354 :     while (fgets(line, sizeof(line), fp) != NULL) {
     150         5970 :         char *t = line;
     151        12580 :         while (*t != '\0') {
     152        18780 :             while (*t != '\0' && isspace((unsigned char)*t)) {
     153         6200 :                 t++;
     154              :             }
     155        12580 :             if (*t == '\0' || strncmp(t, "<!--", 4) == 0) {
     156              :                 break;
     157              :             }
     158              : 
     159         6611 :             char *tagEnd = strchr(t, '>');
     160         6611 :             if (tagEnd == NULL) {
     161            1 :                 break;
     162              :             }
     163              : 
     164         6610 :             if (t[0] == '<' && t[1] == '/') {
     165         2023 :                 if (dc > 0) {
     166         2021 :                     dc--;
     167              :                 }
     168         2023 :                 t = tagEnd + 1;
     169         2023 :                 continue;
     170              :             }
     171              : 
     172         4587 :             if (t[0] == '<') {
     173         4587 :                 t = HandleOpenTag(t, tagEnd, tags, maxTags, cnt, &dc);
     174         4587 :                 if (t == NULL) {
     175            0 :                     return TOPO_ERR_INTERNAL;
     176              :                 }
     177         4587 :                 continue;
     178              :             }
     179            0 :             break;
     180              :         }
     181              :     }
     182          384 :     return TOPO_SUCCESS;
     183              : }
     184              : 
     185              : /* ─── 核心解析函数 ─── */
     186              : 
     187          396 : TopoAddrResult ParseXmlTags(const char *xmlPath, TagEntry *tags, unsigned int *tagCount, unsigned int maxTags)
     188              : {
     189          396 :     *tagCount = 0;
     190              : 
     191          396 :     FILE *fp = fopen(xmlPath, "rb");
     192          396 :     if (fp == NULL) {
     193           11 :         TOPO_ERR("ParseXmlTags: cannot open %s", xmlPath);
     194           11 :         return TOPO_ERR_OPEN_FILE;
     195              :     }
     196              : 
     197              :     struct stat st;
     198          385 :     if (fstat(fileno(fp), &st) != 0 || st.st_size == 0) {
     199            1 :         TOPO_ERR("ParseXmlTags: stat failed or empty file, path=%s", xmlPath);
     200            1 :         fclose(fp);
     201            1 :         return TOPO_ERR_OPEN_FILE;
     202              :     }
     203              : 
     204          384 :     unsigned int cnt = 0;
     205          384 :     if (ParseXmlLines(fp, tags, maxTags, &cnt) != TOPO_SUCCESS) {
     206            0 :         fclose(fp);
     207            0 :         return TOPO_ERR_INTERNAL;
     208              :     }
     209              : 
     210          384 :     fclose(fp);
     211          384 :     *tagCount = cnt;
     212          384 :     if (cnt == 0) {
     213            0 :         TOPO_ERR("ParseXmlTags: no valid tags found in %s", xmlPath);
     214            0 :         return TOPO_ERR_NOT_FOUND;
     215              :     }
     216          384 :     return TOPO_SUCCESS;
     217              : }
        

Generated by: LCOV version 2.0-1