用C语言实现PHP的dirname函数

标签: , , , ,

写一个程序要用到,于是整理了一下。在PHP源码中的ext/standard/string.c中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

/***********************************
Author  : Demon
Website : https://demon.tw
E-mail  : 380401911@qq.com
***********************************/

#define IS_SLASH_P(c)  (*(c) == '/' || (*(c) == '\\' && !IsDBCSLeadByte(*(c-1))))
#define DEFAULT_SLASH  '\\'


char *estrndup(const char *s, size_t length)
{
    char *p;

    p = (char *) malloc(length+1);
    if (p == NULL) {
        return p;
    }
    memcpy(p, s, length);
    p[length] = 0;
    return p;
}


/* {{{ php_dirname
   Returns directory name component of path */
size_t php_dirname(char *path, size_t len)
{
    register char *end = path + len - 1;
    unsigned int len_adjust = 0;

    /* Note that on Win32 CWD is per drive (heritage from CP/M).
     * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
     */
    if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
        /* Skip over the drive spec (if any) so as not to change */
        path += 2;
        len_adjust += 2;
        if (2 == len) {
            /* Return "c:" on Win32 for dirname("c:").
             * It would be more consistent to return "c:." 
             * but that would require making the string *longer*.
             */
            return len;
        }
    }

    if (len == 0) {
        /* Illegal use of this function */
        return 0;
    }

    /* Strip trailing slashes */
    while (end >= path && IS_SLASH_P(end)) {
        end--;
    }
    if (end < path) {
        /* The path only contained slashes */
        path[0] = DEFAULT_SLASH;
        path[1] = '\0';
        return 1 + len_adjust;
    }

    /* Strip filename */
    while (end >= path && !IS_SLASH_P(end)) {
        end--;
    }
    if (end < path) {
        path[0] = '.';
        path[1] = '\0';
        return 1 + len_adjust;
    }

    /* Strip slashes which came before the file name */
    while (end >= path && IS_SLASH_P(end)) {
        end--;
    }
    if (end < path) {
        path[0] = DEFAULT_SLASH;
        path[1] = '\0';
        return 1 + len_adjust;
    }
    *(end+1) = '\0';

    return (size_t)(end + 1 - path) + len_adjust;
}
/* }}} */

/* {{{ proto string dirname(string path)
   Returns the directory name component of the path */
char *dirname(char *str)
{
    char *ret;
    size_t ret_len;

    ret = estrndup(str, strlen(str));
    ret_len = php_dirname(ret, strlen(str));

    return ret;
}
/* }}} */

int main(void)
{
    char *file = dirname("/etc/passwd");
    printf("%s\n", file);
    free(file);
    return 0;
}
赞赏

微信赞赏支付宝赞赏

随机文章:

  1. Windows 10 LTSC 2019 KMS激活
  2. 批处理技术内幕:ECHO命令
  3. NDS模拟器DeSmuME
  4. VBS获取系统本次及上次开关机时间
  5. Msxml2.XMLHTTP和Msxml2.ServerXMLHTTP的区别

一条评论 发表在“用C语言实现PHP的dirname函数”上

  1. 小邓说道:

    man 3 dirname 里说到返回值不要用free,你这个。。。

留下回复