From cfeb386b61341ef5dd85a5320f5854e724e2bdf6 Mon Sep 17 00:00:00 2001 From: kcwu Date: Sun, 27 May 2007 14:08:24 +0000 Subject: * 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 --- mbbsd/board.c | 11 +-- mbbsd/name.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 282 insertions(+), 6 deletions(-) (limited to 'mbbsd') 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 && idxsize); + return self->base[idx]; +} + +static int NameList_MaxLen(const struct NameList *list, int offset, int count) +{ + int i; + int maxlen = 0; + + for(i=offset; isize; 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; isize; 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; isize; 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; isize; 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; isize; 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--) { @@ -378,6 +524,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) { -- cgit v1.2.3