Mercurial > vim
comparison src/filepath.c @ 20643:c2beb6baa42c v8.2.0875
patch 8.2.0875: getting attributes for directory entries is slow
Commit: https://github.com/vim/vim/commit/6c9ba0428041d5316871245be38c13faa0107026
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Jun 1 16:09:41 2020 +0200
patch 8.2.0875: getting attributes for directory entries is slow
Problem: Getting attributes for directory entries is slow.
Solution: Add readdirex(). (Ken Takata, closes https://github.com/vim/vim/issues/5619)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 01 Jun 2020 16:15:03 +0200 |
parents | 4c317d8c1051 |
children | d91b8d1e5198 |
comparison
equal
deleted
inserted
replaced
20642:c0c5e1e1bad9 | 20643:c2beb6baa42c |
---|---|
1027 slash_adjust(rettv->vval.v_string); | 1027 slash_adjust(rettv->vval.v_string); |
1028 #endif | 1028 #endif |
1029 } | 1029 } |
1030 | 1030 |
1031 /* | 1031 /* |
1032 * Convert "st" to file permission string. | |
1033 */ | |
1034 char_u * | |
1035 getfpermst(stat_T *st, char_u *perm) | |
1036 { | |
1037 char_u flags[] = "rwx"; | |
1038 int i; | |
1039 | |
1040 for (i = 0; i < 9; i++) | |
1041 { | |
1042 if (st->st_mode & (1 << (8 - i))) | |
1043 perm[i] = flags[i % 3]; | |
1044 else | |
1045 perm[i] = '-'; | |
1046 } | |
1047 return perm; | |
1048 } | |
1049 | |
1050 /* | |
1032 * "getfperm({fname})" function | 1051 * "getfperm({fname})" function |
1033 */ | 1052 */ |
1034 void | 1053 void |
1035 f_getfperm(typval_T *argvars, typval_T *rettv) | 1054 f_getfperm(typval_T *argvars, typval_T *rettv) |
1036 { | 1055 { |
1037 char_u *fname; | 1056 char_u *fname; |
1038 stat_T st; | 1057 stat_T st; |
1039 char_u *perm = NULL; | 1058 char_u *perm = NULL; |
1040 char_u flags[] = "rwx"; | 1059 char_u permbuf[] = "---------"; |
1041 int i; | |
1042 | 1060 |
1043 fname = tv_get_string(&argvars[0]); | 1061 fname = tv_get_string(&argvars[0]); |
1044 | 1062 |
1045 rettv->v_type = VAR_STRING; | 1063 rettv->v_type = VAR_STRING; |
1046 if (mch_stat((char *)fname, &st) >= 0) | 1064 if (mch_stat((char *)fname, &st) >= 0) |
1047 { | 1065 perm = vim_strsave(getfpermst(&st, permbuf)); |
1048 perm = vim_strsave((char_u *)"---------"); | |
1049 if (perm != NULL) | |
1050 { | |
1051 for (i = 0; i < 9; i++) | |
1052 { | |
1053 if (st.st_mode & (1 << (8 - i))) | |
1054 perm[i] = flags[i % 3]; | |
1055 } | |
1056 } | |
1057 } | |
1058 rettv->vval.v_string = perm; | 1066 rettv->vval.v_string = perm; |
1059 } | 1067 } |
1060 | 1068 |
1061 /* | 1069 /* |
1062 * "getfsize({fname})" function | 1070 * "getfsize({fname})" function |
1104 else | 1112 else |
1105 rettv->vval.v_number = -1; | 1113 rettv->vval.v_number = -1; |
1106 } | 1114 } |
1107 | 1115 |
1108 /* | 1116 /* |
1117 * Convert "st" to file type string. | |
1118 */ | |
1119 char_u * | |
1120 getftypest(stat_T *st) | |
1121 { | |
1122 char *t; | |
1123 | |
1124 if (S_ISREG(st->st_mode)) | |
1125 t = "file"; | |
1126 else if (S_ISDIR(st->st_mode)) | |
1127 t = "dir"; | |
1128 else if (S_ISLNK(st->st_mode)) | |
1129 t = "link"; | |
1130 else if (S_ISBLK(st->st_mode)) | |
1131 t = "bdev"; | |
1132 else if (S_ISCHR(st->st_mode)) | |
1133 t = "cdev"; | |
1134 else if (S_ISFIFO(st->st_mode)) | |
1135 t = "fifo"; | |
1136 else if (S_ISSOCK(st->st_mode)) | |
1137 t = "socket"; | |
1138 else | |
1139 t = "other"; | |
1140 return (char_u*)t; | |
1141 } | |
1142 | |
1143 /* | |
1109 * "getftype({fname})" function | 1144 * "getftype({fname})" function |
1110 */ | 1145 */ |
1111 void | 1146 void |
1112 f_getftype(typval_T *argvars, typval_T *rettv) | 1147 f_getftype(typval_T *argvars, typval_T *rettv) |
1113 { | 1148 { |
1114 char_u *fname; | 1149 char_u *fname; |
1115 stat_T st; | 1150 stat_T st; |
1116 char_u *type = NULL; | 1151 char_u *type = NULL; |
1117 char *t; | |
1118 | 1152 |
1119 fname = tv_get_string(&argvars[0]); | 1153 fname = tv_get_string(&argvars[0]); |
1120 | 1154 |
1121 rettv->v_type = VAR_STRING; | 1155 rettv->v_type = VAR_STRING; |
1122 if (mch_lstat((char *)fname, &st) >= 0) | 1156 if (mch_lstat((char *)fname, &st) >= 0) |
1123 { | 1157 type = vim_strsave(getftypest(&st)); |
1124 if (S_ISREG(st.st_mode)) | |
1125 t = "file"; | |
1126 else if (S_ISDIR(st.st_mode)) | |
1127 t = "dir"; | |
1128 else if (S_ISLNK(st.st_mode)) | |
1129 t = "link"; | |
1130 else if (S_ISBLK(st.st_mode)) | |
1131 t = "bdev"; | |
1132 else if (S_ISCHR(st.st_mode)) | |
1133 t = "cdev"; | |
1134 else if (S_ISFIFO(st.st_mode)) | |
1135 t = "fifo"; | |
1136 else if (S_ISSOCK(st.st_mode)) | |
1137 t = "socket"; | |
1138 else | |
1139 t = "other"; | |
1140 type = vim_strsave((char_u *)t); | |
1141 } | |
1142 rettv->vval.v_string = type; | 1158 rettv->vval.v_string = type; |
1143 } | 1159 } |
1144 | 1160 |
1145 /* | 1161 /* |
1146 * "glob()" function | 1162 * "glob()" function |
1357 | 1373 |
1358 /* | 1374 /* |
1359 * Evaluate "expr" (= "context") for readdir(). | 1375 * Evaluate "expr" (= "context") for readdir(). |
1360 */ | 1376 */ |
1361 static int | 1377 static int |
1362 readdir_checkitem(void *context, char_u *name) | 1378 readdir_checkitem(void *context, void *item) |
1363 { | 1379 { |
1364 typval_T *expr = (typval_T *)context; | 1380 typval_T *expr = (typval_T *)context; |
1365 typval_T save_val; | 1381 typval_T save_val; |
1366 typval_T rettv; | 1382 typval_T rettv; |
1367 typval_T argv[2]; | 1383 typval_T argv[2]; |
1368 int retval = 0; | 1384 int retval = 0; |
1369 int error = FALSE; | 1385 int error = FALSE; |
1370 | 1386 char_u *name = (char_u*)item; |
1371 if (expr->v_type == VAR_UNKNOWN) | |
1372 return 1; | |
1373 | 1387 |
1374 prepare_vimvar(VV_VAL, &save_val); | 1388 prepare_vimvar(VV_VAL, &save_val); |
1375 set_vim_var_string(VV_VAL, name, -1); | 1389 set_vim_var_string(VV_VAL, name, -1); |
1376 argv[0].v_type = VAR_STRING; | 1390 argv[0].v_type = VAR_STRING; |
1377 argv[0].vval.v_string = name; | 1391 argv[0].vval.v_string = name; |
1406 if (rettv_list_alloc(rettv) == FAIL) | 1420 if (rettv_list_alloc(rettv) == FAIL) |
1407 return; | 1421 return; |
1408 path = tv_get_string(&argvars[0]); | 1422 path = tv_get_string(&argvars[0]); |
1409 expr = &argvars[1]; | 1423 expr = &argvars[1]; |
1410 | 1424 |
1411 ret = readdir_core(&ga, path, (void *)expr, readdir_checkitem); | 1425 ret = readdir_core(&ga, path, FALSE, (void *)expr, |
1412 if (ret == OK && rettv->vval.v_list != NULL && ga.ga_len > 0) | 1426 (expr->v_type == VAR_UNKNOWN) ? NULL : readdir_checkitem); |
1427 if (ret == OK) | |
1413 { | 1428 { |
1414 for (i = 0; i < ga.ga_len; i++) | 1429 for (i = 0; i < ga.ga_len; i++) |
1415 { | 1430 { |
1416 p = ((char_u **)ga.ga_data)[i]; | 1431 p = ((char_u **)ga.ga_data)[i]; |
1417 list_append_string(rettv->vval.v_list, p, -1); | 1432 list_append_string(rettv->vval.v_list, p, -1); |
1418 } | 1433 } |
1419 } | 1434 } |
1420 ga_clear_strings(&ga); | 1435 ga_clear_strings(&ga); |
1436 } | |
1437 | |
1438 /* | |
1439 * Evaluate "expr" (= "context") for readdirex(). | |
1440 */ | |
1441 static int | |
1442 readdirex_checkitem(void *context, void *item) | |
1443 { | |
1444 typval_T *expr = (typval_T *)context; | |
1445 typval_T save_val; | |
1446 typval_T rettv; | |
1447 typval_T argv[2]; | |
1448 int retval = 0; | |
1449 int error = FALSE; | |
1450 dict_T *dict = (dict_T*)item; | |
1451 | |
1452 prepare_vimvar(VV_VAL, &save_val); | |
1453 set_vim_var_dict(VV_VAL, dict); | |
1454 argv[0].v_type = VAR_DICT; | |
1455 argv[0].vval.v_dict = dict; | |
1456 | |
1457 if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) | |
1458 goto theend; | |
1459 | |
1460 retval = tv_get_number_chk(&rettv, &error); | |
1461 if (error) | |
1462 retval = -1; | |
1463 clear_tv(&rettv); | |
1464 | |
1465 theend: | |
1466 set_vim_var_dict(VV_VAL, NULL); | |
1467 restore_vimvar(VV_VAL, &save_val); | |
1468 return retval; | |
1469 } | |
1470 | |
1471 /* | |
1472 * "readdirex()" function | |
1473 */ | |
1474 void | |
1475 f_readdirex(typval_T *argvars, typval_T *rettv) | |
1476 { | |
1477 typval_T *expr; | |
1478 int ret; | |
1479 char_u *path; | |
1480 garray_T ga; | |
1481 int i; | |
1482 | |
1483 if (rettv_list_alloc(rettv) == FAIL) | |
1484 return; | |
1485 path = tv_get_string(&argvars[0]); | |
1486 expr = &argvars[1]; | |
1487 | |
1488 ret = readdir_core(&ga, path, TRUE, (void *)expr, | |
1489 (expr->v_type == VAR_UNKNOWN) ? NULL : readdirex_checkitem); | |
1490 if (ret == OK) | |
1491 { | |
1492 for (i = 0; i < ga.ga_len; i++) | |
1493 { | |
1494 dict_T *dict = ((dict_T**)ga.ga_data)[i]; | |
1495 list_append_dict(rettv->vval.v_list, dict); | |
1496 dict_unref(dict); | |
1497 } | |
1498 } | |
1499 ga_clear(&ga); | |
1421 } | 1500 } |
1422 | 1501 |
1423 /* | 1502 /* |
1424 * "readfile()" function | 1503 * "readfile()" function |
1425 */ | 1504 */ |