如何得到内存中的long text 文本 VA01 Check text is empty / default text

本文详细介绍了如何在SAP系统中利用增强函数读取保存在内存中的长文本信息,具体以billinghead为例,展示了从READ_TEXT转换到实际数据库存储文本的流程,并提供了获取特定文本ID文本内容的代码示例。

1、MV45AFZZ

 Check text

FORM USEREXIT_SAVE_DOCUMENT_PREPARE.
*{   INSERT         DEVK900304                                        1
* insert by Lionel to default rejection reason by header status
DATA: BEGIN OF ISTAT OCCURS 0.
        INCLUDE STRUCTURE JSTAT.
DATA: END OF ISTAT.
DATA: L_WFID TYPE ZWFID.
DATA: L_INSTID TYPE SIBFBORIID.
DATA: L_SPID TYPE ZSPID.
DATA: L_WFSTATE TYPE CHAR1.
include fv45ploc.
include fv45eloc.

DATA: Z_STONR LIKE TJ30-STONR.
data: z_updkz like xvbap-updkz.
CALL FUNCTION 'STATUS_READ'
  EXPORTING
    OBJNR                  VBAK-OBJNR
 IMPORTING
    STONR                  Z_STONR
 TABLES
   STATUS                 ISTAT.
if sy-subrc 0.
  case sy-tcode.
    when 'VA01' or 'VA31'.
      z_updkz ' '.
    when 'VA02' or 'VA32'.
      z_updkz 'U'.
    when others.
      z_updkz ' '.
  endcase.
*if sy-mandt <> '120'.
  loop at xvbap.
    svbap-tabix sy-tabix.
    perform vbap_bearbeiten_vorbereiten(sapfv45p).

    Case z_stonr.
* 00 - waiting for approval, 10 - reject by system, ' ' approved
* status 20 = approve, status 30 = reject
      when '20'.
        if vbap-abgru '00' or vbap-abgru '  ' or vbap-abgru '10'.
          vbap-abgru '  '.
        endif.
      when '30'.
        if vbap-abgru '00' or vbap-abgru '  ' or vbap-abgru '10'.
          vbap-abgru '10'.
        endif.
      when '10'.
        if vbap-abgru '00' or vbap-abgru '  ' or vbap-abgru '10'.
          vbap-abgru '00'.
        endif.

    endcase.
    perform vbap_bearbeiten(sapfv45p).
    perform vbap_bearbeiten_ende(sapfv45p).
  endloop.

endif.
*Add Jimmy at 05/08/2013
if sy-tcode 'VA01' or sy-tcode 'VA02'.
  if xvbak-AUART 'OR' or xvbak-AUART 'ZSP' or xvbak-AUART 'ZCOS'
    or xvbak-AUART 'KB' or xvbak-AUART 'KE' or xvbak-AUART 'ZREP'.
     DATA BEGIN OF THEADER.
          INCLUDE STRUCTURE THEAD.
     DATA END OF THEADER.
     data:lv_message type LENGTH 255,
          lv_date type LENGTH 132,
          lv_delidate like sy-datum.
     DATA: LINES LIKE STANDARD TABLE OF TLINE WITH HEADER LINE.
     DATA: LMEMORY_ID(30VALUE 'SAPLSTXD'. "do not change
     data: CATALOG LIKE TCATALOG OCCURS WITH HEADER LINE.
     IMPORT  CATALOG from MEMORY ID 'SAPLSTXD'.

     loop at CATALOG WHERE   TDID 'Z204' and TDOBJECT 'VBBP'.
        clear:LINES,LINES[],THEADER,lv_date,lv_delidate.
        LMEMORY_ID 'SAPLSTXD'.
        CONCATENATE LMEMORY_ID CATALOG-ID INTO LMEMORY_ID.
        IMPORT THEAD TO THEADER
        TLINE TO LINES
        FROM MEMORY ID LMEMORY_ID.
        if not LINES[] is INITIAL.
          READ TABLE lines INDEX 1.
          lv_date LINES-TDLINE.
          if  not lv_date is INITIAL.
            perform change_date_format using lv_date  '' changing lv_delidate.
            if lv_delidate '00000000' or lv_delidate is INITIAL.
              CONCATENATE 'Item' CATALOG-tdname+10(6)  'Customer request delivery date format is error' into lv_message SEPARATED BY space.
              exit.
            endif.
          endif.
        endif.
      endloop.

     if lv_message is NOT INITIAL.
       MESSAGE lv_message TYPE 'E'.
     endif.
  endif.
endif.
*end Jimmy
*}   INSERT


ENDFORM.
*eject
*{   INSERT         DEVK905925                                        1
form change_date_format  using p_old_date
                              p_external
                        changing p_new_date.
  constants:c_chk_date like pa0001-ename value '0123456789/'.

  if p_external 'X'.
    call function 'CONVERT_DATE_TO_EXTERNAL'
      exporting
        date_internal            p_old_date
      importing
        date_external            p_new_date
      exceptions
        date_internal_is_invalid 1
        others                   2.
    if sy-subrc <> 0.
      clear:p_new_date.
    endif.
  else.
    check p_old_date is not initial.
    if p_old_date cn c_chk_date.
      p_new_date '00000000'.
    else.
      call function 'CONVERT_DATE_TO_INTERNAL'
        exporting
          date_external            p_old_date
        importing
          date_internal            p_new_date
        exceptions
          date_external_is_invalid 1
          others                   2.
      if sy-subrc ne 0.
        p_new_date '00000000'.
      endif.
    endif.
  endif.

endform.                    " CHANGE_DATE_FORMAT

 

2、Default text

        data:l_header type standard table of thead with header line,
             l_lines  type standard table of tline with header line,
             l_tdname type tdobname.

 

l_header-tdname vblen posnr

            l_header-tdid  'Z205'.
            l_header-tdobject =  'VBBP'.
            l_header-tdspras sy-langu.
            append l_header.
            l_lines-tdformat '*'.
            l_lines-tdline = ‘dddd’.
            append l_lines.
            call function 'SAVE_TEXT'
              exporting
                client          sy-mandt
                header          l_header
                savemode_direct 'X'
              tables
                lines           l_lines
              exceptions
                id              1
                language        2
                name            3
                object          4
                others          5.

 

 

1.直接可以从READ_TEXT中取长文本。

查找READ_TEXT要填写属性的方法。

 

2.情况描述: (以下为转载)
假设在做me21n,va01,mm01,vf01的时候输入了长本文,在保存的时候想要通过增强得到长文本的内容,是不能通过read_text的function来读取的,原因是该信息还在内存里没有写到数据表STXH中,那么有什么办法能够取到

如果我在billing head的text ID是‘z004’的文本

Biliing的增强是:
Enhancement : SDVFX002 User exit for A/R line in transfer to accounting
Component: EXIT_SAPLV60B_002
所以代码就放到这里面:

DATA BEGIN OF THEADER.
      INCLUDE STRUCTURE THEAD.
 DATA END OF THEADER.
 DATA: LINES LIKE STANDARD TABLE OF TLINE WITH HEADER LINE.
 DATA: LMEMORY_ID(30) VALUE 'SAPLSTXD'. "do not change
 data: CATALOG LIKE TCATALOG OCCURS 0 WITH HEADER LINE.
 IMPORT  CATALOG from MEMORY ID 'SAPLSTXD'.
 READ TABLE CATALOG WITH KEY TDID = 'Z004' TDOBJECT = 'VBBK'.
 CHECK SY-SUBRC = 0.
 CONCATENATE LMEMORY_ID CATALOG-ID INTO LMEMORY_ID.
 IMPORT THEAD TO THEADER
 TLINE TO LINES
 FROM MEMORY ID LMEMORY_ID.

通过这段代码可以得到当前的text文本信息
IMPORT  CATALOG from MEMORY ID ’SAPLSTXD’.
在catalog里面存放的是各个文本的head信息,主要包含了textID TextObject可以看到下面的debug截图:

图中的字段TDOBJECT存放的是billing的head还是item的object, TDID是他的text ID(如果这个ID的text有数值就会包含在这个表中)这里关键的是‘ID’这个字段,把这个字段的值前面加上SAPLSTXD就可以得到想要的文本的路径,如现在我想要抓取billing header的‘Z004’的文本内容,那么它对应的内存地址就是SAPLSTXD000003再通过上图的这些信息,调用
IMPORT THEAD TO THEADER
TLINE TO LINES
FROM MEMORY ID ‘SAPLSTXD000003’.就可以得到billing head的text id是‘z004’的文本内容,得到文本内容,文本内容放在lines内表里,如下图:

/* $$$!!Warning: Huawei key information asset. No spread without permission.$$$ */ /* CODEMARK:rLr9evwLcHFK0ocH1vI5dv79JXrhoRrQ3pUSCsHdOM/puzvFwKILKNePe4bG/B98pz4V5doHi56R 0f3JfrYASX9dpcZzoFk8wkkpq5MAD4RwzrjSTSwmSgk6EZzizHLHkLuwgBO/Olw2XedzCHtebXyo yNB9//dTPbfdMJ7sNDSFMTKompTfgLuL7NhFD5/M8erEHLDuj5Myu6AuUcaewiPD5TZwZAK2sm6H iGAgOSfBGClTYuoXWnVOBg9wy4VM# */ /* $$$!!Warning: Deleting or modifying the preceding information is prohibited.$$$ */ /* * Copyright (c) Shenzhen Yinwang Intelligent Technologies Co., Ltd. 2024. All rights reserved. * Description: Public Domain Tiny Regular Expressions Library * Author: Zhao Quan z00809758 * Date: 2023-7-13 10:33:55 */ #include "tre.h" #include "string.h" #if defined (__ANDROID__) #include <log/log.h> #include <securec.h> #elif defined (__AMP_ARM__) #include <securec.h> #include "asp_log.h" #endif #ifndef TRE_SILENT #include "stdio.h" #include "stdarg.h" #endif #define TRE_MAXQUANT 1024 // Max in {m,n} - must be < ushrt_max - see "struct tre_node" #define TRE_MAXPLUS 40000 // For + and * #define TRE_TYPES_X X(NONE) X(BEGIN) X(END) \ X(QUANT) X(LQUANT) X(QMARK) X(LQMARK) X(STAR) X(LSTAR) X(PLUS) X(LPLUS) \ X(DOT) X(CHAR) X(CLASS) X(NCLASS) X(DIGIT) X(NDIGIT) X(ALPHA) X(NALPHA) X(SPACE) X(NSPACE) #define X(A) TRE_##A, enum { TRE_TYPES_X }; #undef X static int tre_err(const char *format, ...) { #ifdef TRE_SILENT (void) format; #else #if defined (__ANDROID__) || defined (__AMP_ARM__) #define MAX_LOG_LENGTH (500) char _logger_buf[MAX_LOG_LENGTH] = {0}; va_list args; va_start(args, format); (void)vsprintf_s(_logger_buf, MAX_LOG_LENGTH, format, args); va_end(args); ALOGE("[%s]: %s", __FUNCTION__, _logger_buf); #else (void)fputs("Error: ", stderr); va_list args; va_start(args, format); (void)vfprintf(stderr, format, args); va_end(args); (void)fputs("\n", stderr); (void)fflush(stderr); #endif #endif return 0; } TRE_DEF const char *tre_compile_match(const char *pattern, const char *text, const char **end) { tre_comp tregex = {0}; if (tre_compile(pattern, &tregex) == 0) { tre_err("Compiling pattern failed"); return 0; } return tre_match(&tregex, text, end); } static const char *matchpattern(const tre_node *nodes, const char *text, const char *tend); TRE_DEF const char *tre_nmatch(const tre_comp *tregex, const char *text, unsigned tlen, const char **end) { if (tregex == NULL || text == NULL || tlen == 0) { tre_err("NULL text or tre_comp"); return 0; } const char *tend = text + tlen; const char *mend; const tre_node *nodes = tregex->nodes; if (nodes->type == TRE_BEGIN) { mend = matchpattern(nodes + 1, text, tend); if (mend) { if (end) { *end = mend; } return text; } return 0; } do { mend = matchpattern(nodes, text, tend); if (mend) { if (end) { *end = mend; } return text; } } while (tend > text++); return 0; } TRE_DEF const char *tre_match(const tre_comp *tregex, const char *text, const char **end) { return tre_nmatch(tregex, text, (unsigned int)strlen(text), end); } #define TRE_ISMETA(c) (((c)=='s')||((c)=='S')||((c)=='w')||((c)=='W')||((c)=='d')||((c)=='D')) int character_class(const char *pattern, unsigned* i, unsigned* idx, unsigned plen, tre_comp *tregex) { // Copy characters inside [...] to buffer char temp; char *buf = tregex->buffer; unsigned buflen = sizeof tregex->buffer; while (pattern[++(*i)] != ']') { if ((*i) >= plen) { break; } temp = 0; if (pattern[*i] == '\\') { if (++(*i) >= plen) return tre_err("Dangling '\\' in class"); // Only escape metachars and escape, omit escape for others temp = TRE_ISMETA(pattern[*i]); if (temp != 0 || pattern[*i] == '\\') { if ((*idx) > buflen - 2) { // 2 return tre_err("Buffer overflow in %d class", (*i) - 1); } buf[(*idx)++] = '\\'; } } if ((*idx) > buflen - 2) { // 2 return tre_err("Buffer overflow in class"); } buf[(*idx)++] = pattern[*i]; // Check if it is a range if (temp != 0) { continue; // metachar } if (pattern[(*i) + 1] != '-' || (*i) + 2 >= plen || pattern[(*i) + 2] == ']') { // 2 continue; // not '-' or "-"! or "-]" } temp = (pattern[(*i) + 2] == '\\'); // 2 if (temp != 0 && ((*i) + 3 >= plen || TRE_ISMETA(pattern[(*i) + 3]))) { // 3 continue; // "-\\"! or "-\\w" } // Validate range temp = temp != 0 ? pattern[(*i) + 3] : pattern[(*i) + 2]; // 2 3 if (temp < pattern[*i]) { return tre_err("Incorrect range in class"); } } if (pattern[*i] != ']') { return tre_err("Non terminated class"); } buf[(*idx)++] = 0; return 1; } int quantifier(const char *pattern, unsigned* i, unsigned* j, unsigned plen, tre_comp *tregex) { tre_node *tnode = tregex->nodes; //============Code standard modification================== // char *buf = tregex->buffer; // unsigned buflen = sizeof tregex->buffer; unsigned long val = 0; // for parsing numbers in {m,n} (*i)++; do { if (*i >= plen || pattern[*i] < '0' || pattern[*i] > '9') { return tre_err("Non-digit min value in quantifier"); } val = 10 * val + (unsigned) (pattern[(*i)++] - '0'); // 10 } while (pattern[*i] != ',' && pattern[*i] != '}'); if (val > TRE_MAXQUANT) { return tre_err("Min value too big in quantifier"); } tnode[*j].u.mn[0] = (unsigned short)val; if (pattern[*i] == ',') { if (++(*i) >= plen) { return tre_err("Dangling ',' in quantifier"); } if (pattern[*i] == '}') { val = TRE_MAXQUANT; } else { val = 0; while (pattern[*i] != '}') { if (*i >= plen || pattern[*i] < '0' || pattern[*i] > '9') { return tre_err("Non-digit max value in quantifier"); } val = 10 * val + (unsigned) (pattern[(*i)++] - '0'); // 10 } if (val > TRE_MAXQUANT || val < tnode[*j].u.mn[0]) { return tre_err("Max value too big or less than min value in quantifier"); } } } tnode[*j].type = (unsigned char)(((*i) + 1 < plen && pattern[(*i) + 1] == '?') ? ((*i)++, TRE_LQUANT) : TRE_QUANT); tnode[*j].u.mn[1] = (unsigned short)val; return 1; } int escaped_characters(const char *pattern, tre_node *tnode, int i, int j) { switch (pattern[i]) { // Meta-character: case 'd': tnode[j].type = TRE_DIGIT; break; case 'D': tnode[j].type = TRE_NDIGIT; break; case 'w': tnode[j].type = TRE_ALPHA; break; case 'W': tnode[j].type = TRE_NALPHA; break; case 's': tnode[j].type = TRE_SPACE; break; case 'S': tnode[j].type = TRE_NSPACE; break; // Not in [dDwWsS] default: tnode[j].type = TRE_CHAR; tnode[j].u.ch = pattern[i]; break; } //============Code standard modification================== return 1; } int meta_characters(char *quable, tre_node *tnode, unsigned *i, unsigned *j, const char *pattern) { switch (pattern[*i]) { //============Code standard modification================== case '^': *quable = 0; tnode[*j].type = (unsigned char)TRE_BEGIN; break; case '$': *quable = 0; tnode[*j].type = (unsigned char)TRE_END; break; case '.': *quable = 1; tnode[*j].type = (unsigned char)TRE_DOT; break; case '*': if (*quable == 0) { return tre_err("Non-quantifiable before *"); } *quable = 0; if (pattern[(*i) + 1] == '?') { (*i)++; tnode[*j].type = (unsigned char)TRE_LSTAR; } else { tnode[*j].type = (unsigned char)TRE_STAR; } break; case '+': if (*quable == 0) { return tre_err("Non-quantifiable before +"); } *quable = 0; if (pattern[(*i) + 1] == '?') { (*i)++; tnode[*j].type = (unsigned char)TRE_LPLUS; } else { tnode[*j].type = (unsigned char)TRE_PLUS; } break; case '?': if (*quable == 0) { return tre_err("Non-quantifiable before ?"); } *quable = 0; if (pattern[(*i) + 1] == '?') { (*i)++; tnode[*j].type = (unsigned char)TRE_LQMARK; } else { tnode[*j].type = (unsigned char)TRE_QMARK; } break; default: return -1; } return 1; } TRE_DEF int tre_ncompile(const char *pattern, unsigned plen, tre_comp *tregex) { if (tregex == NULL || pattern == NULL || plen == 0) { return tre_err("NULL/empty string or tre_comp"); } tre_node *tnode = tregex->nodes; char *buf = tregex->buffer; char quable = 0; // is the last node quantifiable unsigned idx = 0; unsigned i = 0; // index into pattern unsigned j = 0; // index into tnode while (i < plen && (j + 1 < TRE_MAX_NODES)) { int ret = meta_characters(&quable, tnode, &i, &j, pattern); if (ret == 0) { return 0; } if (ret == -1) { switch (pattern[i]) { // Escaped characters case '\\': { quable = 1; if (++i >= plen) return tre_err("Dangling \\"); escaped_characters(pattern, tnode, (int)i, (int)j); } break; // Character class case '[': { quable = 1; tnode[j].type = (unsigned char)((pattern[i + 1] == '^') ? (i++, TRE_NCLASS) : TRE_CLASS); tnode[j].u.cc = buf + idx; if (character_class(pattern, &i, &idx, plen, tregex) == 0) { return 0; } } break; // Quantifier case '{': { if (quable == 0) { return tre_err("Non-quantifiable before {m,n}"); } quable = 0; if (quantifier(pattern, &i, &j, plen, tregex) == 0) { return 0; } } break; // Regular characters default: { quable = 1; tnode[j].type = TRE_CHAR; tnode[j].u.ch = pattern[i]; } break; } } i++; j++; } // 'TRE_NONE' is a sentinel used to indicate end-of-pattern tnode[j].type = TRE_NONE; return 1; } TRE_DEF int tre_compile(const char *pattern, tre_comp *tregex) { return tre_ncompile(pattern, (unsigned int)strlen(pattern), tregex); } #define TRE_MATCHDIGIT(c) (((c) >= '0') && ((c) <= '9')) #define TRE_MATCHALPHA(c) (((c) >= 'a') && ((c) <= 'z')) || (((c) >= 'A') && ((c) <= 'Z')) #define TRE_MATCHSPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r') || ((c) == '\f') || ((c) == '\v')) #define TRE_MATCHALNUM(c) (((c) == '_') || TRE_MATCHALPHA(c) || TRE_MATCHDIGIT(c)) static int matchmetachar(char c, char mc) { switch (mc) { case 'd': return TRE_MATCHDIGIT(c); case 'D': return !TRE_MATCHDIGIT(c); case 'w': return TRE_MATCHALNUM(c); case 'W': return !TRE_MATCHALNUM(c); case 's': return TRE_MATCHSPACE(c); case 'S': return !TRE_MATCHSPACE(c); default: return (c == mc); } } // note: compiler makes sure '\\' is followed by one of 'dDwWsS\\' static int matchcharclass(char c, const char *str) { char rmax; while (*str != '\0'){ if (str[0] == '\\') { if (matchmetachar(c, str[1]) != 0) { return 1; } str += 2; // 2 if (TRE_ISMETA(*str)) { continue; } } else { if (c == *str) { return 1; } str += 1; } if (*str != '-' || str[1] == '\0') { continue; } rmax = (str[1] == '\\'); if (rmax != 0 && TRE_ISMETA(str[2])) { continue; } rmax = rmax != 0 ? str[2] : str[1]; // 2 if (c >= str[-1] && c <= rmax) { return 1; } str++; } return 0; } #ifndef TRE_DOTANY #define TRE_MATCHDOT(c) (((c) != '\n') && ((c) != '\r')) #else #define TRE_MATCHDOT(c) (1) #endif static int matchone(const tre_node *tnode, char c) { switch (tnode->type) { case TRE_CHAR: return (tnode->u.ch == c); case TRE_DOT: return TRE_MATCHDOT(c); case TRE_CLASS: return matchcharclass(c, tnode->u.cc); case TRE_NCLASS: return matchcharclass(c, tnode->u.cc) == 0; case TRE_DIGIT: return TRE_MATCHDIGIT(c); case TRE_NDIGIT: return !TRE_MATCHDIGIT(c); case TRE_ALPHA: return TRE_MATCHALNUM(c); case TRE_NALPHA: return !TRE_MATCHALNUM(c); case TRE_SPACE: return TRE_MATCHSPACE(c); case TRE_NSPACE: return !TRE_MATCHSPACE(c); default: return 0; } } #undef TRE_MATCHDIGIT #undef TRE_MATCHALPHA #undef TRE_MATCHSPACE #undef TRE_MATCHALNUM #undef TRE_MATCHDOT static const char *matchquant_lazy(const tre_node *nodes, const char *text, const char *tend, unsigned min, unsigned max) { const char *end; max = max - min; while (min != 0 && text < tend && matchone(nodes, *text) != 0) { text++; min--; } if (min != 0) { return 0; } if ((end = matchpattern(nodes + 2, text, tend))) { // 2 return end; } while (max != 0 && text < tend && matchone(nodes, *text) != 0) { text++; max--; if ((end = matchpattern(nodes + 2, text, tend))) {// 2 return end; } } return 0; } static const char *matchquant(const tre_node *nodes, const char *text, const char *tend, unsigned min, unsigned max){ const char *end, *start = text + min; while (max != 0 && text < tend && matchone(nodes, *text) != 0) { text++; max--; } while (text >= start) { if ((end = matchpattern(nodes + 2, text--, tend))) { // 2 return end; } } return 0; } // Iterative matching static const char *matchpattern(const tre_node *nodes, const char *text, const char *tend) { do { if (nodes[0].type == TRE_NONE) { return text; } if ((nodes[0].type == TRE_END) && nodes[1].type == TRE_NONE) { return (text == tend) ? text : 0; } switch (nodes[1].type) { case TRE_QMARK: return matchquant(nodes, text, tend, 0, 1); case TRE_LQMARK: return matchquant_lazy(nodes, text, tend, 0, 1); case TRE_QUANT: return matchquant(nodes, text, tend, nodes[1].u.mn[0], nodes[1].u.mn[1]); case TRE_LQUANT: return matchquant_lazy(nodes, text, tend, nodes[1].u.mn[0], nodes[1].u.mn[1]); case TRE_STAR: return matchquant(nodes, text, tend, 0, TRE_MAXPLUS); case TRE_LSTAR: return matchquant_lazy(nodes, text, tend, 0, TRE_MAXPLUS); case TRE_PLUS: return matchquant(nodes, text, tend, 1, TRE_MAXPLUS); case TRE_LPLUS: return matchquant_lazy(nodes, text, tend, 1, TRE_MAXPLUS); default: break; } } while (text < tend && (matchone(nodes++, *text++) != 0)); return 0; } void tre_print(const tre_comp *tregex) { #ifdef TRE_SILENT (void) tregex; #else #define X(A) #A, static const char *tre_typenames[] = { TRE_TYPES_X }; #undef X if (!tregex) { #ifndef __AMP_ARM__ printf("NULL compiled regex detected\n"); #endif return; } const tre_node *tnode = tregex->nodes; int i; for (i = 0; i < TRE_MAX_NODES; ++i) { if (tnode[i].type == TRE_NONE) { break; } #ifndef __AMP_ARM__ printf("type: %s", tre_typenames[tnode[i].type]); if (tnode[i].type == TRE_CLASS || tnode[i].type == TRE_NCLASS) { printf(" \"%s\"", tnode[i].u.cc); } else if (tnode[i].type == TRE_QUANT || tnode[i].type == TRE_LQUANT) { printf(" {%hu,%hu}", tnode[i].u.mn[0], tnode[i].u.mn[1]); } else if (tnode[i].type == TRE_CHAR) { printf(" '%c'", tnode[i].u.ch); } printf("\n"); #endif } #endif // TRE_SILENT } #undef TRE_TYPES_X /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - MIT License Copyright (c) 2018 kokke, monolifed Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ 有不符合c语言代码规范的地方吗 格式规范也包括
06-12
// /* // * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. // */ // #include "tre.h" // // 如需使用华为安全函数,请加上 #include "securec.h" // double AddNumbers(const double f1, const double f2) // { // return f1 + f2; // } /* $$$!!Warning: Huawei key information asset. No spread without permission.$$$ */ /* CODEMARK:rLr9evwLcHFK0ocH1vI5dv79JXrhoRrQ3pUSCsHdOM/puzvFwKILKNePe4bG/B98pz4V5doHi56R 0f3JfrYASX9dpcZzoFk8wkkpq5MAD4RwzrjSTSwmSgk6EZzizHLHkLuwgBO/Olw2XedzCHtebXyo yNB9//dTPbfdMJ7sNDSFMTKompTfgLuL7NhFD5/M8erEHLDuj5Myu6AuUcaewiPD5TZwZAK2sm6H iGAgOSfBGClTYuoXWnVOBg9wy4VM# */ /* $$$!!Warning: Deleting or modifying the preceding information is prohibited.$$$ */ /* * Copyright (c) Shenzhen Yinwang Intelligent Technologies Co., Ltd. 2024. All rights reserved. * Description: Public Domain Tiny Regular Expressions Library * Author: Zhao Quan z00809758 * Date: 2023-7-13 10:33:55 */ #include "tre.h" #include "string.h" #if defined (__ANDROID__) #include <log/log.h> #include <securec.h> #elif defined (__AMP_ARM__) #include <securec.h> #include "asp_log.h" #endif #ifndef TRE_SILENT #include "stdio.h" #include "stdarg.h" #endif #define TRE_MAXQUANT 1024 // Max in {m,n} - must be < ushrt_max - see "struct tre_node" #define TRE_MAXPLUS 40000 // For + and * #define TRE_TYPES_X X(NONE) X(BEGIN) X(END) \ X(QUANT) X(LQUANT) X(QMARK) X(LQMARK) X(STAR) X(LSTAR) X(PLUS) X(LPLUS) \ X(DOT) X(CHAR) X(CLASS) X(NCLASS) X(DIGIT) X(NDIGIT) X(ALPHA) X(NALPHA) X(SPACE) X(NSPACE) #define X(A) TRE_##A, enum { TRE_TYPES_X }; #undef X static int tre_err(const char *format, ...) { #ifdef TRE_SILENT (void) format; #else #if defined (__ANDROID__) || defined (__AMP_ARM__) #define MAX_LOG_LENGTH (500) char _logger_buf[MAX_LOG_LENGTH] = {0}; va_list args; va_start(args, format); (void)vsprintf_s(_logger_buf, MAX_LOG_LENGTH, format, args); va_end(args); ALOGE("[%s]: %s", __FUNCTION__, _logger_buf); #else (void)fputs("Error: ", stderr); va_list args; va_start(args, format); (void)vfprintf(stderr, format, args); va_end(args); (void)fputs("\n", stderr); (void)fflush(stderr); #endif #endif return 0; } TRE_DEF const char *tre_compile_match(const char *pattern, const char *text, const char **end) { tre_comp tregex = {0}; if (tre_compile(pattern, &tregex) == 0) { tre_err("Compiling pattern failed"); return 0; } return tre_match(&tregex, text, end); } static const char *matchpattern(const tre_node *nodes, const char *text, const char *tend); TRE_DEF const char *tre_nmatch(const tre_comp *tregex, const char *text, unsigned tlen, const char **end) { if (tregex == NULL || text == NULL || tlen == 0) { tre_err("NULL text or tre_comp"); return 0; } const char *tend = text + tlen; const char *mend; const tre_node *nodes = tregex->nodes; if (nodes->type == TRE_BEGIN) { mend = matchpattern(nodes + 1, text, tend); if (mend) { if (end) *end = mend; return text; } return 0; } do { mend = matchpattern(nodes, text, tend); if (mend) { if (end) *end = mend; return text; } } while (tend > text++); return 0; } TRE_DEF const char *tre_match(const tre_comp *tregex, const char *text, const char **end) { return tre_nmatch(tregex, text, (unsigned int)strlen(text), end); } #define TRE_ISMETA(c) (((c)=='s')||((c)=='S')||((c)=='w')||((c)=='W')||((c)=='d')||((c)=='D')) int character_class(const char *pattern, unsigned* i, unsigned* idx, unsigned plen, tre_comp *tregex) { // Copy characters inside [...] to buffer char temp; char *buf = tregex->buffer; unsigned buflen = sizeof tregex->buffer; while (pattern[++(*i)] != ']') { if ((*i) >= plen) { break; } temp = 0; if (pattern[*i] == '\\') { if (++(*i) >= plen) return tre_err("Dangling '\\' in class"); // Only escape metachars and escape, omit escape for others temp = TRE_ISMETA(pattern[*i]); if (temp != 0 || pattern[*i] == '\\') { if ((*idx) > buflen - 2) // 2 return tre_err("Buffer overflow in %d class", (*i) - 1); buf[(*idx)++] = '\\'; } } if ((*idx) > buflen - 2) // 2 return tre_err("Buffer overflow in class"); buf[(*idx)++] = pattern[*i]; // Check if it is a range if (temp != 0) continue; // metachar if (pattern[(*i) + 1] != '-' || (*i) + 2 >= plen || pattern[(*i) + 2] == ']') // 2 continue; // not '-' or "-"! or "-]" temp = (pattern[(*i) + 2] == '\\'); // 2 if (temp != 0 && ((*i) + 3 >= plen || TRE_ISMETA(pattern[(*i) + 3]))) // 3 continue; // "-\\"! or "-\\w" // Validate range temp = temp != 0 ? pattern[(*i) + 3] : pattern[(*i) + 2]; // 2 3 if (temp < pattern[*i]) return tre_err("Incorrect range in class"); } if (pattern[*i] != ']') return tre_err("Non terminated class"); buf[(*idx)++] = 0; return 1; } int quantifier(const char *pattern, unsigned* i, unsigned* j, unsigned plen, tre_comp *tregex) { tre_node *tnode = tregex->nodes; //============Code standard modification================== // char *buf = tregex->buffer; // unsigned buflen = sizeof tregex->buffer; unsigned long val = 0; // for parsing numbers in {m,n} (*i)++; do { if (*i >= plen || pattern[*i] < '0' || pattern[*i] > '9') return tre_err("Non-digit min value in quantifier"); val = 10 * val + (unsigned) (pattern[(*i)++] - '0'); // 10 } while (pattern[*i] != ',' && pattern[*i] != '}'); if (val > TRE_MAXQUANT) return tre_err("Min value too big in quantifier"); tnode[*j].u.mn[0] = (unsigned short)val; if (pattern[*i] == ',') { if (++(*i) >= plen) return tre_err("Dangling ',' in quantifier"); if (pattern[*i] == '}') { val = TRE_MAXQUANT; } else { val = 0; while (pattern[*i] != '}') { if (*i >= plen || pattern[*i] < '0' || pattern[*i] > '9') return tre_err("Non-digit max value in quantifier"); val = 10 * val + (unsigned) (pattern[(*i)++] - '0'); // 10 } if (val > TRE_MAXQUANT || val < tnode[*j].u.mn[0]) return tre_err("Max value too big or less than min value in quantifier"); } } tnode[*j].type = (unsigned char)(((*i) + 1 < plen && pattern[(*i) + 1] == '?') ? ((*i)++, TRE_LQUANT) : TRE_QUANT); tnode[*j].u.mn[1] = (unsigned short)val; return 1; } int escaped_characters(const char *pattern, tre_node *tnode, int i, int j) { switch (pattern[i]) { // Meta-character: case 'd': tnode[j].type = TRE_DIGIT; break; case 'D': tnode[j].type = TRE_NDIGIT; break; case 'w': tnode[j].type = TRE_ALPHA; break; case 'W': tnode[j].type = TRE_NALPHA; break; case 's': tnode[j].type = TRE_SPACE; break; case 'S': tnode[j].type = TRE_NSPACE; break; // Not in [dDwWsS] default: tnode[j].type = TRE_CHAR; tnode[j].u.ch = pattern[i]; break; } } int meta_characters(char *quable, tre_node *tnode, unsigned *i, unsigned *j, const char *pattern) { switch (pattern[*i]) { case '^': quable = 0; tnode[*j].type = (unsigned char)TRE_BEGIN; break; case '$': quable = 0; tnode[*j].type = (unsigned char)TRE_END; break; case '.': quable = 1; tnode[*j].type = (unsigned char)TRE_DOT; break; case '*': if (quable == 0) return tre_err("Non-quantifiable before *"); quable = 0; if (pattern[(*i) + 1] == '?') { (*i)++; tnode[*j].type = (unsigned char)TRE_LSTAR; } else { tnode[*j].type = (unsigned char)TRE_STAR; } break; case '+': if (quable == 0) return tre_err("Non-quantifiable before +"); quable = 0; if (pattern[(*i) + 1] == '?') { (*i)++; tnode[*j].type = (unsigned char)TRE_LPLUS; } else { tnode[*j].type = (unsigned char)TRE_PLUS; } break; case '?': if (quable == 0) return tre_err("Non-quantifiable before ?"); quable = 0; if (pattern[(*i) + 1] == '?') { (*i)++; tnode[*j].type = (unsigned char)TRE_LQMARK; } else { tnode[*j].type = (unsigned char)TRE_QMARK; } break; default: return -1; } return 1; } TRE_DEF int tre_ncompile(const char *pattern, unsigned plen, tre_comp *tregex) { if (tregex == NULL || pattern == NULL || plen == 0) return tre_err("NULL/empty string or tre_comp"); tre_node *tnode = tregex->nodes; char *buf = tregex->buffer; char quable = 0; // is the last node quantifiable unsigned idx = 0; unsigned i = 0; // index into pattern unsigned j = 0; // index into tnode while (i < plen && (j + 1 < TRE_MAX_NODES)) { int ret = meta_characters(&quable, tnode, &i, &j, pattern); if (ret == 0) return 0; if (ret == -1) { switch (pattern[i]) { // Escaped characters case '\\': { quable = 1; if (++i >= plen) return tre_err("Dangling \\"); escaped_characters(pattern, tnode, (int)i, (int)j); } break; // Character class case '[': { quable = 1; tnode[j].type = (unsigned char)((pattern[i + 1] == '^') ? (i++, TRE_NCLASS) : TRE_CLASS); tnode[j].u.cc = buf + idx; if (character_class(pattern, &i, &idx, plen, tregex) == 0) return 0; } break; // Quantifier case '{': { if (quable == 0) return tre_err("Non-quantifiable before {m,n}"); quable = 0; if (quantifier(pattern, &i, &j, plen, tregex) == 0) return 0; } break; // Regular characters default: quable = 1; tnode[j].type = TRE_CHAR; tnode[j].u.ch = pattern[i]; break; } } i++; j++; } // 'TRE_NONE' is a sentinel used to indicate end-of-pattern tnode[j].type = TRE_NONE; return 1; } TRE_DEF int tre_compile(const char *pattern, tre_comp *tregex) { return tre_ncompile(pattern, (unsigned int)strlen(pattern), tregex); } #define TRE_MATCHDIGIT(c) (((c) >= '0') && ((c) <= '9')) #define TRE_MATCHALPHA(c) (((c) >= 'a') && ((c) <= 'z')) || (((c) >= 'A') && ((c) <= 'Z')) #define TRE_MATCHSPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r') || ((c) == '\f') || ((c) == '\v')) #define TRE_MATCHALNUM(c) (((c) == '_') || TRE_MATCHALPHA(c) || TRE_MATCHDIGIT(c)) static int matchmetachar(char c, char mc) { switch (mc) { case 'd': return TRE_MATCHDIGIT(c); case 'D': return !TRE_MATCHDIGIT(c); case 'w': return TRE_MATCHALNUM(c); case 'W': return !TRE_MATCHALNUM(c); case 's': return TRE_MATCHSPACE(c); case 'S': return !TRE_MATCHSPACE(c); default: return (c == mc); } } // note: compiler makes sure '\\' is followed by one of 'dDwWsS\\' static int matchcharclass(char c, const char *str) { char rmax; while (*str != '\0') { if (str[0] == '\\') { if (matchmetachar(c, str[1]) != 0) return 1; str += 2; // 2 if (TRE_ISMETA(*str)) continue; } else { if (c == *str) return 1; str += 1; } if (*str != '-' || str[1] == '\0') continue; rmax = (str[1] == '\\'); if (rmax != 0 && TRE_ISMETA(str[2])) continue; rmax = rmax != 0 ? str[2] : str[1]; // 2 if (c >= str[-1] && c <= rmax) return 1; str++; } return 0; } #ifndef TRE_DOTANY #define TRE_MATCHDOT(c) (((c) != '\n') && ((c) != '\r')) #else #define TRE_MATCHDOT(c) (1) #endif static int matchone(const tre_node *tnode, char c) { switch (tnode->type) { case TRE_CHAR: return (tnode->u.ch == c); case TRE_DOT: return TRE_MATCHDOT(c); case TRE_CLASS: return matchcharclass(c, tnode->u.cc); case TRE_NCLASS: return matchcharclass(c, tnode->u.cc) == 0; case TRE_DIGIT: return TRE_MATCHDIGIT(c); case TRE_NDIGIT: return !TRE_MATCHDIGIT(c); case TRE_ALPHA: return TRE_MATCHALNUM(c); case TRE_NALPHA: return !TRE_MATCHALNUM(c); case TRE_SPACE: return TRE_MATCHSPACE(c); case TRE_NSPACE: return !TRE_MATCHSPACE(c); default: return 0; } } #undef TRE_MATCHDIGIT #undef TRE_MATCHALPHA #undef TRE_MATCHSPACE #undef TRE_MATCHALNUM #undef TRE_MATCHDOT static const char *matchquant_lazy(const tre_node *nodes, const char *text, const char *tend, unsigned min, unsigned max) { const char *end; max = max - min; while (min != 0 && text < tend && matchone(nodes, *text) != 0) { text++; min--; } if (min != 0) return 0; if ((end = matchpattern(nodes + 2, text, tend))) // 2 return end; while (max != 0 && text < tend && matchone(nodes, *text) != 0) { text++; max--; if ((end = matchpattern(nodes + 2, text, tend))) // 2 return end; } return 0; } static const char *matchquant(const tre_node *nodes, const char *text, const char *tend, unsigned min, unsigned max) { const char *end, *start = text + min; while (max != 0 && text < tend && matchone(nodes, *text) != 0) { text++; max--; } while (text >= start) { if ((end = matchpattern(nodes + 2, text--, tend))) // 2 return end; } return 0; } // Iterative matching static const char *matchpattern(const tre_node *nodes, const char *text, const char *tend) { do { if (nodes[0].type == TRE_NONE) return text; if ((nodes[0].type == TRE_END) && nodes[1].type == TRE_NONE) return (text == tend) ? text : 0; switch (nodes[1].type) { case TRE_QMARK: return matchquant(nodes, text, tend, 0, 1); case TRE_LQMARK: return matchquant_lazy(nodes, text, tend, 0, 1); case TRE_QUANT: return matchquant(nodes, text, tend, nodes[1].u.mn[0], nodes[1].u.mn[1]); case TRE_LQUANT: return matchquant_lazy(nodes, text, tend, nodes[1].u.mn[0], nodes[1].u.mn[1]); case TRE_STAR: return matchquant(nodes, text, tend, 0, TRE_MAXPLUS); case TRE_LSTAR: return matchquant_lazy(nodes, text, tend, 0, TRE_MAXPLUS); case TRE_PLUS: return matchquant(nodes, text, tend, 1, TRE_MAXPLUS); case TRE_LPLUS: return matchquant_lazy(nodes, text, tend, 1, TRE_MAXPLUS); default: break; } } while (text < tend && (matchone(nodes++, *text++) != 0)); return 0; } void tre_print(const tre_comp *tregex) { #ifdef TRE_SILENT (void) tregex; #else #define X(A) #A, static const char *tre_typenames[] = { TRE_TYPES_X }; #undef X if (!tregex) { #ifndef __AMP_ARM__ printf("NULL compiled regex detected\n"); #endif return; } const tre_node *tnode = tregex->nodes; int i; for (i = 0; i < TRE_MAX_NODES; ++i) { if (tnode[i].type == TRE_NONE) break; #ifndef __AMP_ARM__ printf("type: %s", tre_typenames[tnode[i].type]); if (tnode[i].type == TRE_CLASS || tnode[i].type == TRE_NCLASS) { printf(" \"%s\"", tnode[i].u.cc); } else if (tnode[i].type == TRE_QUANT || tnode[i].type == TRE_LQUANT) { printf(" {%hu,%hu}", tnode[i].u.mn[0], tnode[i].u.mn[1]); } else if (tnode[i].type == TRE_CHAR) { printf(" '%c'", tnode[i].u.ch); } printf("\n"); #endif } #endif // TRE_SILENT } #undef TRE_TYPES_X /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - MIT License Copyright (c) 2018 kokke, monolifed Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ 以上问题在代码中要怎么修改
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值