libass分析3-源码分析-libass中的宏定义分析

发布时间:2024年01月11日
Author: wencoo
Blog:https://wencoo.blog.csdn.net/
Date: 25/12/2023
Email: jianwen056@aliyun.com
Wechat:wencoo824
QQ:1419440391
Details:

目录

正文 或 背景

NEXT

宏定义实现如下:

#define NEXT(str,token) \
    token = next_token(&str); \
    if (!token) break;

解析字符串str,获取逗号前的项给token,同时str的指针进行移动,移动到下一个项起始地址。

next_token

实现:

static char *next_token(char **str)
{
    char *p;
    char *start;
    skip_spaces(str);
    if (**str == '\0') {
        return 0;
    }

    advance_token_pos((const char**)str,
                      (const char**)&start,
                      (const char**)&p);

    *p = '\0';
    return start;
}

实现的功能就是在字符串str中,解析,获取,(逗号)为间隔的一个项start,进行返回,同时修改了str指针的位置。

advance_token_pos

实现:

// skip spaces in str beforehand, or trim leading spaces afterwards
// 事先跳过STR中的空格,或在之后修剪前导空格
static inline void advance_token_pos(const char **const str,
                                     const char **const start,
                                     const char **const end)
{
    *start = *str;
    *end   = *start;
    while (**end != '\0' && **end != ',') ++*end;
    *str = *end + (**end == ',');
    rskip_spaces((char**)end, (char*)*start);
}

获取字符串中,(逗号)之前的内容

rskip_spaces

实现:

static inline void rskip_spaces(char **str, char *limit)
{
    char *p = *str;
    while ((p > limit) && ((p[-1] == ' ') || (p[-1] == '\t')))
        --p;
    *str = p;
}

反向对字符串进行检查,获取空格之后的字符串。 将获取的字符串地址传给str。

PARSE_START 与PARSE_END

/* One section started with PARSE_START and PARSE_END parses a single token
 * (contained in the variable named token) for the header indicated by the
 * variable tname. It does so by chaining a number of else-if statements, each
 * of which checks if the tname variable indicates that this header should be
 * parsed. The first parameter of the macro gives the name of the header.
 *
 * The string that is passed is in str. str is advanced to the next token if
 * a header could be parsed. The parsed results are stored in the variable
 * target, which has the type ASS_Style* or ASS_Event*.
 */
#define PARSE_START if (0) {
#define PARSE_END   }

这两个宏定义定义了一个完整的if结构,看上去是这样的,给人的第一感觉就是这个样子,

if (0){

}

但是实际上,可能并不是这样的结构,中间使用了更多的宏定义,其中可能包含了很多隐藏结构,需要仔细甄别,例如

if (0){
		STARREDSTRVAL(Name)
// 	#define STARREDSTRVAL(name) \
//    } else if (ass_strcasecmp(tname, #name) == 0) { \
//        while (*token == '*') ++token; \
//        char *new_str = strdup(token); \
//        if (new_str) { \
//            free(target->name); \
//            target->name = new_str; \
//        } 
}

可以看到if(0)没有执行,早已跳到了else逻辑,这就是PARSE_START下面逻辑可以执行的原因。

STARREDSTRVAL

实现:

#define STARREDSTRVAL(name) \
    } else if (ass_strcasecmp(tname, #name) == 0) { \
        while (*token == '*') ++token; \
        char *new_str = strdup(token); \
        if (new_str) { \
            free(target->name); \
            target->name = new_str; \
        }

查找字符串Name,不包含带有*的字符串,然后将Name的数据赋值给target,也就是外部的ASS_Style *target;

ass_strcasecmp

实现:

int ass_strcasecmp(const char *s1, const char *s2)
{
    unsigned char a, b;

    do {
        a = lowertab[(unsigned char)*s1++];
        b = lowertab[(unsigned char)*s2++];
    } while (a && a == b);

    return a - b;
}

对比s1和s2,如果s1和s2相等,那么返回0。

strdup

#define strdup ass_strdup_fallback

定义了一个函数调用,其实现:

// Fallbacks
#ifndef HAVE_STRDUP
char *ass_strdup_fallback(const char *str)
{
    size_t len    = strlen(str) + 1;
    char *new_str = malloc(len);
    if (new_str)
        memcpy(new_str, str, len);
    return new_str;
}
#endif

给str字符串申请了空间,放在堆里面备用。

STRVAL

和STARREDSTRVAL功能类似,该宏定义实现的功能是查找字符串Name,然后将Name的数据赋值给target,也就是外部的ASS_Style *target;,没有检查包含带有*的字符串的功能

实现:

#define STRVAL(name) \
    } else if (ass_strcasecmp(tname, #name) == 0) { \
        char *new_str = strdup(token); \
        if (new_str) { \
            free(target->name); \
            target->name = new_str; \
        }

其余待写,其实到这里,后面的都大同小异,相同的分析思路。

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 wencoo824。QQ:1419440391。

参考

技术交流

欢迎加微信,搜索"wencoo824",进行技术交流,备注”博客音视频技术交流“

文章来源:https://blog.csdn.net/bootleader/article/details/135539572
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。