diff options
author | kcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-05-27 22:08:24 +0800 |
---|---|---|
committer | kcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-05-27 22:08:24 +0800 |
commit | cfeb386b61341ef5dd85a5320f5854e724e2bdf6 (patch) | |
tree | 7a935d79f8c788ca7696279b1a3aa1f519e551fd | |
parent | a8ac9d593f193d06a2dff50bb91f81bfee6b9a94 (diff) | |
download | pttbbs-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.h | 6 | ||||
-rw-r--r-- | include/pttstruct.h | 6 | ||||
-rw-r--r-- | mbbsd/board.c | 11 | ||||
-rw-r--r-- | mbbsd/name.c | 277 |
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; |