免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2199 | 回复: 3
打印 上一主题 下一主题

求解释一段简化路径的代码…… [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-24 21:52 |只看该作者 |倒序浏览
看lighttpd中一段简化路径的代码,看得吐血……

我稍微简化了一下,用gdb调,感觉大致明白了意思,但是理不清楚其中具体的逻辑,特别是while循环那一段……有什么好办法啊?
  1. #include <assert.h>
  2. #include <stdio.h>

  3. /* Remove "/../", "//", "/./" parts from path.
  4. *
  5. * /blah/..         gets  /
  6. * /blah/../foo     gets  /foo
  7. * /abc/./xyz       gets  /abc/xyz
  8. * /abc//xyz        gets  /abc/xyz
  9. *
  10. * NOTE: src and dest can point to the same buffer, in which case,
  11. *       the operation is performed in-place.
  12. */
  13. int buffer_path_simplify(char *dest, char *src)
  14. {
  15.         int toklen;
  16.         char c, pre1;
  17.         char *start, *slash, *walk, *out;
  18.         unsigned short pre;

  19.         if (src == NULL || dest == NULL)
  20.                 return -1;

  21.         walk  = src;
  22.         start = dest;
  23.         out   = dest;
  24.         slash = dest;

  25.         while (*walk == ' ') {
  26.                 walk++;
  27.         }

  28.         pre1 = *(walk++);
  29.         c    = *(walk++);
  30.         pre  = pre1;
  31.         if (pre1 != '/') {
  32.                 pre = ('/' << 8) | pre1;
  33.                 *(out++) = '/';
  34.         }
  35.         *(out++) = pre1;

  36.         if (pre1 == '\0') {
  37.                 return 0;
  38.         }

  39.         while (1) {
  40.                 if (c == '/' || c == '\0') {
  41.                         toklen = out - slash;
  42.                         if (toklen == 3 && pre == (('.' << 8) | '.')) {
  43.                                 out = slash;
  44.                                 if (out > start) {
  45.                                         out--;
  46.                                         while (out > start && *out != '/') {
  47.                                                 out--;
  48.                                         }
  49.                                 }

  50.                                 if (c == '\0')
  51.                                         out++;
  52.                         } else if (toklen == 1 || pre == (('/' << 8) | '.')) {
  53.                                 out = slash;
  54.                                 if (c == '\0')
  55.                                         out++;
  56.                         }

  57.                         slash = out;
  58.                 }

  59.                 if (c == '\0')
  60.                         break;

  61.                 pre1 = c;
  62.                 pre  = (pre << 8) | pre1;
  63.                 c    = *walk;
  64.                 *out = pre1;

  65.                 out++;
  66.                 walk++;
  67.         }

  68.         *out = '\0';

  69.         return 0;
  70. }

  71. int main (int argc, char *argv[])
  72. {
  73.         char buf[1024] = {0};
  74.         assert (argc == 2);

  75.         buffer_path_simplify (buf, argv[1]);

  76.         printf ("%s\n", buf);
  77.        
  78.         return 0;
  79. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-01-24 23:24 |只看该作者
那个是对“/a/b/c/../../b/../”这种做精简
因为“/a/b/c/../../b/../” 就等于“/a/”

然后 它的比较是采用的short类型(变量pre)进行的比较,这样可以一次比较两个字节(如果是按字节比较,则有&&运算符),对代码有一定的简化作用

理清了也好懂

论坛徽章:
0
3 [报告]
发表于 2011-01-25 09:19 |只看该作者
这一点我还是明白的,但是像这种比较复杂的逻辑……

要怎么确定这个循环能正确的结束,得到正确的结果

或者是用循环不变式来验证:

1.循环初始化时是正确的;
2.每一次迭代的结果都是正确的;
3.循环结束时的结果也是正确的。

我得好好琢磨一下

论坛徽章:
0
4 [报告]
发表于 2011-01-26 13:50 |只看该作者
蛮好懂的代码啊
有点bug,就是 36行,所写,就必须要求是以 '/'开头的路径,相对路径就不对了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP