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 */