summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2007-05-27 22:08:24 +0800
committerkcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2007-05-27 22:08:24 +0800
commitcfeb386b61341ef5dd85a5320f5854e724e2bdf6 (patch)
tree7a935d79f8c788ca7696279b1a3aa1f519e551fd
parenta8ac9d593f193d06a2dff50bb91f81bfee6b9a94 (diff)
downloadpttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.tar
pttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.tar.gz
pttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.tar.bz2
pttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.tar.lz
pttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.tar.xz
pttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.tar.zst
pttbbs-cfeb386b61341ef5dd85a5320f5854e724e2bdf6.zip
* rewrite namecomplete2. Avoid small allocation, e.g. linked list,
since some allocator, e.g. dielibc, may not return memory to OS. This saves about 1gb memory for ptt. git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@3517 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--include/proto.h6
-rw-r--r--include/pttstruct.h6
-rw-r--r--mbbsd/board.c11
-rw-r--r--mbbsd/name.c277
4 files changed, 294 insertions, 6 deletions
diff --git a/include/proto.h b/include/proto.h
index 12700e29..1d482e55 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -412,6 +412,12 @@ typedef int (*gnc_comp_func)(int, const char*, int);
typedef int (*gnc_perm_func)(int);
typedef char* (*gnc_getname_func)(int);
+extern void NameList_init(struct NameList *self);
+extern void NameList_delete(struct NameList *self);
+extern void NameList_clear(struct NameList *self);
+extern void NameList_add(struct NameList *self, const char *name);
+extern void namecomplete2(struct NameList *namelist, const char *prompt, char *data);
+
void usercomplete(const char *prompt, char *data);
void namecomplete(const char *prompt, char *data);
void AddNameList(const char *name);
diff --git a/include/pttstruct.h b/include/pttstruct.h
index 67fa00cf..64aac0ac 100644
--- a/include/pttstruct.h
+++ b/include/pttstruct.h
@@ -652,6 +652,12 @@ typedef struct word_t {
struct word_t *next;
} word_t;
+struct NameList {
+ int size;
+ int capacity;
+ char (*base)[IDLEN+1];
+};
+
typedef struct commands_t {
int (*cmdfunc)();
int level;
diff --git a/mbbsd/board.c b/mbbsd/board.c
index bb23d3ba..8a228287 100644
--- a/mbbsd/board.c
+++ b/mbbsd/board.c
@@ -410,17 +410,18 @@ search_board(void)
{
int num;
char genbuf[IDLEN + 2];
+ struct NameList namelist;
+
move(0, 0);
clrtoeol();
- CreateNameList();
+ NameList_init(&namelist);
assert(brdnum<=nbrdsize);
for (num = 0; num < brdnum; num++)
if (!IS_LISTING_FAV() ||
(nbrd[num].myattr & NBRD_BOARD && HasBoardPerm(B_BH(&nbrd[num]))) )
- AddNameList(B_BH(&nbrd[num])->brdname);
- namecomplete(MSG_SELECT_BOARD, genbuf);
- FreeNameList();
- toplev = NULL;
+ NameList_add(&namelist, B_BH(&nbrd[num])->brdname);
+ namecomplete2(&namelist, MSG_SELECT_BOARD, genbuf);
+ NameList_delete(&namelist);
#ifdef DEBUG
vmsg(genbuf);
diff --git a/mbbsd/name.c b/mbbsd/name.c
index aafc4cc6..4457abae 100644
--- a/mbbsd/name.c
+++ b/mbbsd/name.c
@@ -7,6 +7,151 @@ static char * const msg_more = "-- More --";
typedef char (*arrptr)[];
/* name complete for user ID */
+//-----------------------------------------------------------------------
+
+void NameList_init(struct NameList *self)
+{
+ self->size = 0;
+ self->capacity = 0;
+ self->base = NULL;
+}
+
+void NameList_delete(struct NameList *self)
+{
+ self->size = 0;
+ self->capacity = 0;
+ if(self->base)
+ free(self->base);
+ self->base = NULL;
+}
+
+void NameList_clear(struct NameList *self)
+{
+ NameList_delete(self);
+ NameList_init(self);
+}
+
+static void NameList_resizefor(struct NameList *self, int size)
+{
+ int capacity = size * (IDLEN+1);
+#define MIN_CAPACITY 4096
+ if (capacity == 0) {
+ if(self->base) free(self->base);
+ self->base = NULL;
+ self->capacity = 0;
+ } else {
+ int old_capacity = self->capacity;
+ assert(capacity > 0);
+ if (self->capacity == 0)
+ self->capacity = MIN_CAPACITY;
+ if (self->capacity > capacity && self->capacity > MIN_CAPACITY)
+ self->capacity /= 2;
+ if (self->capacity < capacity)
+ self->capacity *= 2;
+
+ if(old_capacity != self->capacity || self->base == NULL) {
+ char (*tmp)[IDLEN+1] = (char(*)[IDLEN+1])malloc((IDLEN+1)*self->capacity);
+ assert(tmp);
+ if (self->size)
+ memcpy(tmp, self->base, (IDLEN+1)*self->size);
+ if (self->base)
+ free(self->base);
+ self->base = tmp;
+ }
+ }
+}
+
+void NameList_add(struct NameList *self, const char *name)
+{
+ NameList_resizefor(self, self->size+1);
+ strlcpy(self->base[self->size], name, IDLEN+1);
+ self->size++;
+}
+
+const char* NameList_get(struct NameList *self, int idx)
+{
+ assert(0<=idx && idx<self->size);
+ return self->base[idx];
+}
+
+static int NameList_MaxLen(const struct NameList *list, int offset, int count)
+{
+ int i;
+ int maxlen = 0;
+
+ for(i=offset; i<list->size; i++) {
+ int len = strlen(list->base[i]);
+ if (len > maxlen)
+ maxlen = len;
+ }
+ assert(maxlen <= IDLEN);
+ return maxlen;
+}
+
+int NameList_match(const struct NameList *src, struct NameList *dst, int key, int pos)
+{
+ int uckey, lckey;
+ int i;
+
+ NameList_clear(dst);
+
+ uckey = chartoupper(key);
+ if (key >= 'A' && key <= 'Z')
+ lckey = key | 0x20;
+ else
+ lckey = key;
+
+ for(i=0; i<src->size; i++) {
+ int ch = src->base[i][pos];
+ if (ch == lckey || ch == uckey)
+ NameList_add(dst, src->base[i]);
+ }
+
+ return dst->size;
+}
+
+int NameList_length(struct NameList *self)
+{
+ return self->size;
+}
+
+void NameList_sublist(struct NameList *src, struct NameList *dst, char *tag)
+{
+ int i;
+ int len;
+ NameList_clear(dst);
+
+ len = strlen(tag);
+ for(i=0; i<src->size; i++)
+ if(len==0 || strncasecmp(src->base[i], tag, len)==0)
+ NameList_add(dst, src->base[i]);
+}
+
+int NameList_remove(struct NameList *self, const char *name)
+{
+ int i;
+ for(i=0; i<self->size; i++)
+ if(strcasecmp(self->base[i], name)==0) {
+ strcpy(self->base[i], self->base[self->size-1]);
+
+ self->size--;
+ NameList_resizefor(self, self->size);
+ return 1;
+ }
+ return 0;
+}
+
+int NameList_search(const struct NameList *self, const char *name)
+{
+ int i;
+ for(i=0; i<self->size; i++)
+ if (strcasecmp(self->base[i], name)==0)
+ return 1;
+ return 0;
+}
+
+//-----------------------------------------------------------------------
+
static int
UserMaxLen(char cwlist[][IDLEN + 1], int cwnum, int morenum,
int count)
@@ -251,6 +396,7 @@ MaxLen(const word_t * list, int count)
return len;
}
+/* TODO use namecomplete2() instead */
void
namecomplete(const char *prompt, char *data)
{
@@ -307,7 +453,7 @@ namecomplete(const char *prompt, char *data)
move(2, 0);
clrtobot();
printdash("相關資訊一覽表", 0);
- while (len + col < 80) {
+ while (len + col < t_columns) {
int i;
for (i = p_lines; (morelist) && (i > 0); i--) {
@@ -379,6 +525,135 @@ namecomplete(const char *prompt, char *data)
}
void
+namecomplete2(struct NameList *namelist, const char *prompt, char *data)
+{
+ char *temp;
+ int x, y, origx, origy;
+ int ch;
+ int count = 0;
+ int clearbot = NA;
+ struct NameList sublist;
+ int viewoffset = 0;
+
+ NameList_init(&sublist);
+
+ NameList_sublist(namelist, &sublist, "");
+ temp = data;
+
+ outs(prompt);
+ clrtoeol();
+ getyx(&y, &x);
+ standout();
+ prints("%*s", IDLEN + 1, "");
+ standend();
+ move(y, x);
+ origy = y; origx = x;
+ viewoffset = 0;
+
+ while ((ch = igetch()) != EOF) {
+ if (ch == '\n' || ch == '\r') {
+ *temp = '\0';
+ if (NameList_length(&sublist)==1)
+ strcpy(data, NameList_get(&sublist, 0));
+ else if (!NameList_search(&sublist, data))
+ data[0] = '\0';
+ NameList_delete(&sublist);
+ break;
+ }
+ if (ch == ' ') {
+ int col, len;
+
+ if (NameList_length(&sublist) == 1) {
+ strcpy(data, NameList_get(&sublist, 0));
+ move(y, x);
+ outs(data + count);
+ count = strlen(data);
+ temp = data + count;
+ getyx(&y, &x);
+ continue;
+ }
+ clearbot = YEA;
+ col = 0;
+ len = NameList_MaxLen(&sublist, viewoffset, p_lines);
+ move(2, 0);
+ clrtobot();
+ printdash("相關資訊一覽表", 0);
+ while (len + col < t_columns) {
+ int i;
+
+ for (i = p_lines; viewoffset < NameList_length(&sublist) && (i > 0); i--) {
+ move(3 + (p_lines - i), col);
+ outs(NameList_get(&sublist, viewoffset));
+ viewoffset++;
+ }
+ col += len + 2;
+ if (viewoffset == NameList_length(&sublist)) {
+ viewoffset = 0;
+ break;
+ }
+ len = NameList_MaxLen(&sublist, viewoffset, p_lines);
+ }
+ if (viewoffset < NameList_length(&sublist)) {
+ vmsg(msg_more);
+ }
+ move(y, x);
+ continue;
+ }
+ if (ch == '\177' || ch == '\010') {
+ if (temp == data)
+ continue;
+ temp--;
+ count--;
+ *temp = '\0';
+ NameList_sublist(namelist, &sublist, data);
+ viewoffset = 0;
+ x--;
+ move(y, x);
+ outc(' ');
+ move(y, x);
+ continue;
+ }
+ if (count < STRLEN && isprint(ch)) {
+ struct NameList tmplist;
+ NameList_init(&tmplist);
+
+ *temp++ = ch;
+ count++;
+ *temp = '\0';
+
+ NameList_sublist(&sublist, &tmplist, data);
+ if (NameList_length(&tmplist)==0) {
+ NameList_delete(&tmplist);
+ temp--;
+ *temp = '\0';
+ count--;
+ continue;
+ }
+ NameList_delete(&sublist);
+ sublist = tmplist;
+ viewoffset = 0;
+ move(y, x);
+ outc(ch);
+ x++;
+ }
+ }
+ if (ch == EOF)
+ /* longjmp(byebye, -1); */
+ raise(SIGHUP); /* jochang: don't know if this is
+ * necessary... */
+ outc('\n');
+ if (clearbot) {
+ move(2, 0);
+ clrtobot();
+ }
+ if (*data) {
+ move(origy, origx);
+ outs(data);
+ outc('\n');
+ }
+}
+
+void
usercomplete(const char *prompt, char *data)
{
char *temp;