Mercurial > vim
comparison src/if_lua.c @ 16076:a2f0e93a5857 v8.1.1043
patch 8.1.1043: Lua interface does not support Blob
commit https://github.com/vim/vim/commit/b78286903300477bb8578a47b8170b4551e290c8
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Mar 23 13:57:02 2019 +0100
patch 8.1.1043: Lua interface does not support Blob
Problem: Lua interface does not support Blob.
Solution: Add support to Blob. (Ozaki Kiichi, closes https://github.com/vim/vim/issues/4151)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 23 Mar 2019 14:00:06 +0100 |
parents | 8ad2cda3757d |
children | 643fe07aa0e2 |
comparison
equal
deleted
inserted
replaced
16075:5ca428f99af9 | 16076:a2f0e93a5857 |
---|---|
26 | 26 |
27 typedef buf_T *luaV_Buffer; | 27 typedef buf_T *luaV_Buffer; |
28 typedef win_T *luaV_Window; | 28 typedef win_T *luaV_Window; |
29 typedef dict_T *luaV_Dict; | 29 typedef dict_T *luaV_Dict; |
30 typedef list_T *luaV_List; | 30 typedef list_T *luaV_List; |
31 typedef blob_T *luaV_Blob; | |
31 typedef struct { | 32 typedef struct { |
32 char_u *name; // funcref | 33 char_u *name; // funcref |
33 dict_T *self; // selfdict | 34 dict_T *self; // selfdict |
34 } luaV_Funcref; | 35 } luaV_Funcref; |
35 typedef void (*msgfunc_T)(char_u *); | 36 typedef void (*msgfunc_T)(char_u *); |
36 | 37 |
37 static const char LUAVIM_DICT[] = "dict"; | 38 static const char LUAVIM_DICT[] = "dict"; |
38 static const char LUAVIM_LIST[] = "list"; | 39 static const char LUAVIM_LIST[] = "list"; |
40 static const char LUAVIM_BLOB[] = "blob"; | |
39 static const char LUAVIM_FUNCREF[] = "funcref"; | 41 static const char LUAVIM_FUNCREF[] = "funcref"; |
40 static const char LUAVIM_BUFFER[] = "buffer"; | 42 static const char LUAVIM_BUFFER[] = "buffer"; |
41 static const char LUAVIM_WINDOW[] = "window"; | 43 static const char LUAVIM_WINDOW[] = "window"; |
42 static const char LUAVIM_FREE[] = "luaV_free"; | 44 static const char LUAVIM_FREE[] = "luaV_free"; |
43 static const char LUAVIM_LUAEVAL[] = "luaV_luaeval"; | 45 static const char LUAVIM_LUAEVAL[] = "luaV_luaeval"; |
66 luaL_error(L, msg ": cannot convert value"); \ | 68 luaL_error(L, msg ": cannot convert value"); \ |
67 } while (0) | 69 } while (0) |
68 | 70 |
69 static luaV_List *luaV_pushlist(lua_State *L, list_T *lis); | 71 static luaV_List *luaV_pushlist(lua_State *L, list_T *lis); |
70 static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic); | 72 static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic); |
73 static luaV_Blob *luaV_pushblob(lua_State *L, blob_T *blo); | |
71 static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name); | 74 static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name); |
72 | 75 |
73 #if LUA_VERSION_NUM <= 501 | 76 #if LUA_VERSION_NUM <= 501 |
74 #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) | 77 #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) |
75 #define luaL_typeerror luaL_typerror | 78 #define luaL_typeerror luaL_typerror |
539 lua_pushnil(L); | 542 lua_pushnil(L); |
540 break; | 543 break; |
541 case VAR_FUNC: | 544 case VAR_FUNC: |
542 luaV_pushfuncref(L, tv->vval.v_string); | 545 luaV_pushfuncref(L, tv->vval.v_string); |
543 break; | 546 break; |
547 case VAR_BLOB: | |
548 luaV_pushblob(L, tv->vval.v_blob); | |
549 break; | |
544 default: | 550 default: |
545 lua_pushnil(L); | 551 lua_pushnil(L); |
546 } | 552 } |
547 } | 553 } |
548 | 554 |
580 break; | 586 break; |
581 case LUA_TUSERDATA: | 587 case LUA_TUSERDATA: |
582 { | 588 { |
583 void *p = lua_touserdata(L, pos); | 589 void *p = lua_touserdata(L, pos); |
584 | 590 |
585 if (lua_getmetatable(L, pos)) /* has metatable? */ | 591 if (lua_getmetatable(L, pos)) // has metatable? |
586 { | 592 { |
587 /* check list */ | 593 // check list |
588 luaV_getfield(L, LUAVIM_LIST); | 594 luaV_getfield(L, LUAVIM_LIST); |
589 if (lua_rawequal(L, -1, -2)) | 595 if (lua_rawequal(L, -1, -2)) |
590 { | 596 { |
591 tv->v_type = VAR_LIST; | 597 tv->v_type = VAR_LIST; |
592 tv->vval.v_list = *((luaV_List *) p); | 598 tv->vval.v_list = *((luaV_List *) p); |
593 ++tv->vval.v_list->lv_refcount; | 599 ++tv->vval.v_list->lv_refcount; |
594 lua_pop(L, 2); /* MTs */ | 600 lua_pop(L, 2); // MTs |
595 break; | 601 break; |
596 } | 602 } |
597 /* check dict */ | 603 // check dict |
598 luaV_getfield(L, LUAVIM_DICT); | 604 luaV_getfield(L, LUAVIM_DICT); |
599 if (lua_rawequal(L, -1, -3)) | 605 if (lua_rawequal(L, -1, -3)) |
600 { | 606 { |
601 tv->v_type = VAR_DICT; | 607 tv->v_type = VAR_DICT; |
602 tv->vval.v_dict = *((luaV_Dict *) p); | 608 tv->vval.v_dict = *((luaV_Dict *) p); |
603 ++tv->vval.v_dict->dv_refcount; | 609 ++tv->vval.v_dict->dv_refcount; |
604 lua_pop(L, 3); /* MTs */ | 610 lua_pop(L, 3); // MTs |
605 break; | 611 break; |
606 } | 612 } |
607 /* check funcref */ | 613 // check blob |
614 luaV_getfield(L, LUAVIM_BLOB); | |
615 if (lua_rawequal(L, -1, -4)) | |
616 { | |
617 tv->v_type = VAR_BLOB; | |
618 tv->vval.v_blob = *((luaV_Blob *) p); | |
619 ++tv->vval.v_blob->bv_refcount; | |
620 lua_pop(L, 4); // MTs | |
621 break; | |
622 } | |
623 // check funcref | |
608 luaV_getfield(L, LUAVIM_FUNCREF); | 624 luaV_getfield(L, LUAVIM_FUNCREF); |
609 if (lua_rawequal(L, -1, -4)) | 625 if (lua_rawequal(L, -1, -5)) |
610 { | 626 { |
611 luaV_Funcref *f = (luaV_Funcref *) p; | 627 luaV_Funcref *f = (luaV_Funcref *) p; |
612 func_ref(f->name); | 628 func_ref(f->name); |
613 tv->v_type = VAR_FUNC; | 629 tv->v_type = VAR_FUNC; |
614 tv->vval.v_string = vim_strsave(f->name); | 630 tv->vval.v_string = vim_strsave(f->name); |
615 lua_pop(L, 4); /* MTs */ | 631 lua_pop(L, 5); // MTs |
616 break; | 632 break; |
617 } | 633 } |
618 lua_pop(L, 4); /* MTs */ | 634 lua_pop(L, 4); // MTs |
619 } | 635 } |
620 } | 636 } |
621 /* FALLTHROUGH */ | 637 // FALLTHROUGH |
622 default: | 638 default: |
623 tv->v_type = VAR_NUMBER; | 639 tv->v_type = VAR_NUMBER; |
624 tv->vval.v_number = 0; | 640 tv->vval.v_number = 0; |
625 status = FAIL; | 641 status = FAIL; |
626 } | 642 } |
751 | 767 |
752 static int | 768 static int |
753 luaV_list_len(lua_State *L) | 769 luaV_list_len(lua_State *L) |
754 { | 770 { |
755 list_T *l = luaV_unbox(L, luaV_List, 1); | 771 list_T *l = luaV_unbox(L, luaV_List, 1); |
756 lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); | 772 lua_pushinteger(L, (int) list_len(l)); |
757 return 1; | 773 return 1; |
758 } | 774 } |
759 | 775 |
760 static int | 776 static int |
761 luaV_list_iter(lua_State *L) | 777 luaV_list_iter(lua_State *L) |
907 | 923 |
908 static int | 924 static int |
909 luaV_dict_len(lua_State *L) | 925 luaV_dict_len(lua_State *L) |
910 { | 926 { |
911 dict_T *d = luaV_unbox(L, luaV_Dict, 1); | 927 dict_T *d = luaV_unbox(L, luaV_Dict, 1); |
912 lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); | 928 lua_pushinteger(L, (int) dict_len(d)); |
913 return 1; | 929 return 1; |
914 } | 930 } |
915 | 931 |
916 static int | 932 static int |
917 luaV_dict_iter(lua_State *L UNUSED) | 933 luaV_dict_iter(lua_State *L UNUSED) |
1023 {"__tostring", luaV_dict_tostring}, | 1039 {"__tostring", luaV_dict_tostring}, |
1024 {"__len", luaV_dict_len}, | 1040 {"__len", luaV_dict_len}, |
1025 {"__call", luaV_dict_call}, | 1041 {"__call", luaV_dict_call}, |
1026 {"__index", luaV_dict_index}, | 1042 {"__index", luaV_dict_index}, |
1027 {"__newindex", luaV_dict_newindex}, | 1043 {"__newindex", luaV_dict_newindex}, |
1044 {NULL, NULL} | |
1045 }; | |
1046 | |
1047 | |
1048 /* ======= Blob type ======= */ | |
1049 | |
1050 static luaV_Blob * | |
1051 luaV_newblob(lua_State *L, blob_T *blo) | |
1052 { | |
1053 luaV_Blob *b = (luaV_Blob *) lua_newuserdata(L, sizeof(luaV_Blob)); | |
1054 *b = blo; | |
1055 blo->bv_refcount++; /* reference in Lua */ | |
1056 luaV_setudata(L, blo); /* cache[blo] = udata */ | |
1057 luaV_getfield(L, LUAVIM_BLOB); | |
1058 lua_setmetatable(L, -2); | |
1059 return b; | |
1060 } | |
1061 | |
1062 luaV_pushtype(blob_T, blob, luaV_Blob) | |
1063 luaV_type_tostring(blob, LUAVIM_BLOB) | |
1064 | |
1065 static int | |
1066 luaV_blob_gc(lua_State *L) | |
1067 { | |
1068 blob_T *b = luaV_unbox(L, luaV_Blob, 1); | |
1069 blob_unref(b); | |
1070 return 0; | |
1071 } | |
1072 | |
1073 static int | |
1074 luaV_blob_len(lua_State *L) | |
1075 { | |
1076 blob_T *b = luaV_unbox(L, luaV_Blob, 1); | |
1077 lua_pushinteger(L, (int) blob_len(b)); | |
1078 return 1; | |
1079 } | |
1080 | |
1081 static int | |
1082 luaV_blob_index(lua_State *L) | |
1083 { | |
1084 blob_T *b = luaV_unbox(L, luaV_Blob, 1); | |
1085 if (lua_isnumber(L, 2)) | |
1086 { | |
1087 int idx = luaL_checkinteger(L, 2); | |
1088 if (idx < blob_len(b)) | |
1089 lua_pushnumber(L, (lua_Number) blob_get(b, idx)); | |
1090 else | |
1091 lua_pushnil(L); | |
1092 } | |
1093 else if (lua_isstring(L, 2)) | |
1094 { | |
1095 const char *s = lua_tostring(L, 2); | |
1096 if (strncmp(s, "add", 3) == 0) | |
1097 { | |
1098 lua_getmetatable(L, 1); | |
1099 lua_getfield(L, -1, s); | |
1100 } | |
1101 else | |
1102 lua_pushnil(L); | |
1103 } | |
1104 else | |
1105 lua_pushnil(L); | |
1106 return 1; | |
1107 } | |
1108 | |
1109 static int | |
1110 luaV_blob_newindex(lua_State *L) | |
1111 { | |
1112 blob_T *b = luaV_unbox(L, luaV_Blob, 1); | |
1113 if (b->bv_lock) | |
1114 luaL_error(L, "blob is locked"); | |
1115 if (lua_isnumber(L, 2)) | |
1116 { | |
1117 long len = blob_len(b); | |
1118 int idx = luaL_checkinteger(L, 2); | |
1119 int val = luaL_checkinteger(L, 3); | |
1120 if (idx < len || (idx == len && ga_grow(&b->bv_ga, 1) == OK)) | |
1121 { | |
1122 blob_set(b, idx, (char_u) val); | |
1123 if (idx == len) | |
1124 ++b->bv_ga.ga_len; | |
1125 } | |
1126 else | |
1127 luaL_error(L, "index out of range"); | |
1128 } | |
1129 return 0; | |
1130 } | |
1131 | |
1132 static int | |
1133 luaV_blob_add(lua_State *L) | |
1134 { | |
1135 luaV_Blob *blo = luaV_checkudata(L, 1, LUAVIM_BLOB); | |
1136 blob_T *b = (blob_T *) luaV_checkcache(L, (void *) *blo); | |
1137 if (b->bv_lock) | |
1138 luaL_error(L, "blob is locked"); | |
1139 lua_settop(L, 2); | |
1140 if (!lua_isstring(L, 2)) | |
1141 luaL_error(L, "string expected, got %s", luaL_typename(L, 2)); | |
1142 else | |
1143 { | |
1144 size_t i, l = 0; | |
1145 const char *s = lua_tolstring(L, 2, &l); | |
1146 | |
1147 ga_grow(&b->bv_ga, l); | |
1148 for (i = 0; i < l; ++i) | |
1149 ga_append(&b->bv_ga, s[i]); | |
1150 } | |
1151 lua_settop(L, 1); | |
1152 return 1; | |
1153 } | |
1154 | |
1155 static const luaL_Reg luaV_Blob_mt[] = { | |
1156 {"__tostring", luaV_blob_tostring}, | |
1157 {"__gc", luaV_blob_gc}, | |
1158 {"__len", luaV_blob_len}, | |
1159 {"__index", luaV_blob_index}, | |
1160 {"__newindex", luaV_blob_newindex}, | |
1161 {"add", luaV_blob_add}, | |
1028 {NULL, NULL} | 1162 {NULL, NULL} |
1029 }; | 1163 }; |
1030 | 1164 |
1031 | 1165 |
1032 /* ======= Funcref type ======= */ | 1166 /* ======= Funcref type ======= */ |
1622 } | 1756 } |
1623 return 1; | 1757 return 1; |
1624 } | 1758 } |
1625 | 1759 |
1626 static int | 1760 static int |
1761 luaV_blob(lua_State *L) | |
1762 { | |
1763 blob_T *b; | |
1764 int initarg = !lua_isnoneornil(L, 1); | |
1765 | |
1766 if (initarg && !lua_isstring(L, 1)) | |
1767 luaL_error(L, "string expected, got %s", luaL_typename(L, 1)); | |
1768 b = blob_alloc(); | |
1769 if (b == NULL) | |
1770 lua_pushnil(L); | |
1771 else | |
1772 { | |
1773 luaV_newblob(L, b); | |
1774 if (initarg) | |
1775 { | |
1776 size_t i, l = 0; | |
1777 const char *s = lua_tolstring(L, 1, &l); | |
1778 | |
1779 ga_grow(&b->bv_ga, l); | |
1780 for (i = 0; i < l; ++i) | |
1781 ga_append(&b->bv_ga, s[i]); | |
1782 } | |
1783 } | |
1784 return 1; | |
1785 } | |
1786 | |
1787 static int | |
1627 luaV_funcref(lua_State *L) | 1788 luaV_funcref(lua_State *L) |
1628 { | 1789 { |
1629 const char *name = luaL_checkstring(L, 1); | 1790 const char *name = luaL_checkstring(L, 1); |
1630 /* note: not checking if function exists (needs function_exists) */ | 1791 /* note: not checking if function exists (needs function_exists) */ |
1631 if (name == NULL || *name == NUL || VIM_ISDIGIT(*name)) | 1792 if (name == NULL || *name == NUL || VIM_ISDIGIT(*name)) |
1713 } | 1874 } |
1714 luaV_getfield(L, LUAVIM_DICT); | 1875 luaV_getfield(L, LUAVIM_DICT); |
1715 if (lua_rawequal(L, -1, 2)) | 1876 if (lua_rawequal(L, -1, 2)) |
1716 { | 1877 { |
1717 lua_pushstring(L, "dict"); | 1878 lua_pushstring(L, "dict"); |
1879 return 1; | |
1880 } | |
1881 luaV_getfield(L, LUAVIM_BLOB); | |
1882 if (lua_rawequal(L, -1, 2)) | |
1883 { | |
1884 lua_pushstring(L, "blob"); | |
1718 return 1; | 1885 return 1; |
1719 } | 1886 } |
1720 luaV_getfield(L, LUAVIM_FUNCREF); | 1887 luaV_getfield(L, LUAVIM_FUNCREF); |
1721 if (lua_rawequal(L, -1, 2)) | 1888 if (lua_rawequal(L, -1, 2)) |
1722 { | 1889 { |
1746 {"eval", luaV_eval}, | 1913 {"eval", luaV_eval}, |
1747 {"beep", luaV_beep}, | 1914 {"beep", luaV_beep}, |
1748 {"line", luaV_line}, | 1915 {"line", luaV_line}, |
1749 {"list", luaV_list}, | 1916 {"list", luaV_list}, |
1750 {"dict", luaV_dict}, | 1917 {"dict", luaV_dict}, |
1918 {"blob", luaV_blob}, | |
1751 {"funcref", luaV_funcref}, | 1919 {"funcref", luaV_funcref}, |
1752 {"buffer", luaV_buffer}, | 1920 {"buffer", luaV_buffer}, |
1753 {"window", luaV_window}, | 1921 {"window", luaV_window}, |
1754 {"open", luaV_open}, | 1922 {"open", luaV_open}, |
1755 {"type", luaV_type}, | 1923 {"type", luaV_type}, |
1881 lua_pushvalue(L, 1); | 2049 lua_pushvalue(L, 1); |
1882 luaV_openlib(L, luaV_List_mt, 1); | 2050 luaV_openlib(L, luaV_List_mt, 1); |
1883 luaV_newmetatable(L, LUAVIM_DICT); | 2051 luaV_newmetatable(L, LUAVIM_DICT); |
1884 lua_pushvalue(L, 1); | 2052 lua_pushvalue(L, 1); |
1885 luaV_openlib(L, luaV_Dict_mt, 1); | 2053 luaV_openlib(L, luaV_Dict_mt, 1); |
2054 luaV_newmetatable(L, LUAVIM_BLOB); | |
2055 lua_pushvalue(L, 1); | |
2056 luaV_openlib(L, luaV_Blob_mt, 1); | |
1886 luaV_newmetatable(L, LUAVIM_FUNCREF); | 2057 luaV_newmetatable(L, LUAVIM_FUNCREF); |
1887 lua_pushvalue(L, 1); | 2058 lua_pushvalue(L, 1); |
1888 luaV_openlib(L, luaV_Funcref_mt, 1); | 2059 luaV_openlib(L, luaV_Funcref_mt, 1); |
1889 luaV_newmetatable(L, LUAVIM_BUFFER); | 2060 luaV_newmetatable(L, LUAVIM_BUFFER); |
1890 lua_pushvalue(L, 1); /* cache table */ | 2061 lua_pushvalue(L, 1); /* cache table */ |