用C语言实现PHP的dirname函数

标签: , , , ,

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


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

/***********************************
Author  : Demon
Website : http://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. cURL 7.22.0 with zlib SSL and IPv6 support
  2. 禁用Windows系统的临时IPv6地址
  3. VeryPDF CHM to PDF Converter 2.0 注册码
  4. VBS的一个BUG
  5. 本地机器和Windows 2003远程桌面之间复制粘贴文件

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

  1. 小邓说道:

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

留下回复