Mercurial > hg > nnchat
comparison libnnchat.c @ 103:eaa524e153f9
Initial implementation of functions for implementing tab-completion for user names.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 15 Oct 2010 00:34:25 +0300 |
parents | b096ae97fc7d |
children | c587a99e2096 |
comparison
equal
deleted
inserted
replaced
102:b096ae97fc7d | 103:eaa524e153f9 |
---|---|
548 | 548 |
549 return res; | 549 return res; |
550 } | 550 } |
551 | 551 |
552 | 552 |
553 char * nn_editbuf_get_string(nn_editbuf_t *buf, ssize_t start, ssize_t end) | |
554 { | |
555 char *str; | |
556 ssize_t siz; | |
557 | |
558 if (buf == NULL) | |
559 return NULL; | |
560 | |
561 if (start < 0 || end > buf->len || start >= buf->len) | |
562 return NULL; | |
563 | |
564 if (end < 0) { | |
565 siz = buf->len - start + 1; | |
566 } else if (start <= end) { | |
567 siz = end - start + 1; | |
568 } else | |
569 return NULL; | |
570 | |
571 str = th_malloc(siz + 1); | |
572 memcpy(str, buf->data + start, siz); | |
573 str[siz] = 0; | |
574 return str; | |
575 } | |
576 | |
577 | |
553 void nn_editbuf_setpos(nn_editbuf_t *buf, ssize_t pos) | 578 void nn_editbuf_setpos(nn_editbuf_t *buf, ssize_t pos) |
554 { | 579 { |
555 /* Check arguments */ | 580 assert(buf != NULL); |
581 | |
556 if (pos < 0) | 582 if (pos < 0) |
557 buf->pos = 0; | 583 buf->pos = 0; |
558 else if (pos >= buf->len) | 584 else if (pos >= buf->len) |
559 buf->pos = buf->len; | 585 buf->pos = buf->len; |
560 else | 586 else |
562 } | 588 } |
563 | 589 |
564 | 590 |
565 static uint8_t nn_hash_user(const char *name) | 591 static uint8_t nn_hash_user(const char *name) |
566 { | 592 { |
593 /* | |
567 int n = 0; | 594 int n = 0; |
568 const uint8_t *c = (uint8_t *)name; | 595 const uint8_t *c = (uint8_t *)name; |
569 uint8_t hash = 0xff; | 596 uint8_t hash = 0xff; |
570 | 597 |
571 while (*c && n < 4) { | 598 while (*c && n < 4) { |
572 hash = (hash << 1) ^ tolower(*c); | 599 hash = (hash << 1) ^ tolower(*c); |
573 c++; n++; | 600 c++; n++; |
574 } | 601 } |
575 | 602 |
576 return (hash & 0xff); | 603 return (hash & 0xff); |
604 */ | |
605 return tolower(name[0]); | |
577 } | 606 } |
578 | 607 |
579 | 608 |
580 static void nn_user_insert(nn_user_t **list, nn_user_t *node) | 609 static void nn_user_insert(nn_user_t **list, nn_user_t *node) |
581 { | 610 { |
582 node->next = *list; | 611 node->next = *list; |
583 *list = node; | 612 *list = node; |
613 } | |
614 | |
615 | |
616 nn_user_t *nn_userhash_foreach(const nn_userhash_t *list, int (*func)(const nn_user_t *)) | |
617 { | |
618 int i; | |
619 | |
620 if (list == NULL) return NULL; | |
621 | |
622 for (i = 0; i < NN_NUM_BUCKETS; i++) | |
623 if (list->buckets[i] != NULL) { | |
624 nn_user_t *curr = list->buckets[i]; | |
625 while (curr != NULL) { | |
626 if (func(curr) != 0) | |
627 return curr; | |
628 curr = curr->next; | |
629 } | |
630 } | |
631 | |
632 return NULL; | |
584 } | 633 } |
585 | 634 |
586 | 635 |
587 nn_user_t *nn_user_find_enc(const nn_userhash_t *list, const char *encname) | 636 nn_user_t *nn_user_find_enc(const nn_userhash_t *list, const char *encname) |
588 { | 637 { |
602 | 651 |
603 return NULL; | 652 return NULL; |
604 } | 653 } |
605 | 654 |
606 | 655 |
607 int nn_user_add_to_hash(nn_userhash_t **list, const char *encname) | 656 nn_user_t *nn_user_match(const nn_userhash_t *list, const char *str, const char *current) |
657 { | |
658 uint8_t hash; | |
659 | |
660 if (list == NULL) return NULL; | |
661 | |
662 hash = nn_hash_user(str); | |
663 if (list->buckets[hash] != NULL) { | |
664 nn_user_t *curr = list->buckets[hash]; | |
665 int len = strlen(str); | |
666 | |
667 if (current != NULL) { | |
668 nn_user_t *found = NULL; | |
669 while (curr != NULL) { | |
670 if (strcasecmp(curr->name, current) == 0) { | |
671 found = curr->next; | |
672 break; | |
673 } | |
674 curr = curr->next; | |
675 } | |
676 if (found != NULL) | |
677 curr = found; | |
678 else | |
679 curr = list->buckets[hash]; | |
680 } | |
681 | |
682 while (curr != NULL) { | |
683 if (strncasecmp(curr->name, str, len) == 0) | |
684 return curr; | |
685 curr = curr->next; | |
686 } | |
687 } | |
688 | |
689 return NULL; | |
690 } | |
691 | |
692 | |
693 nn_userhash_t *nn_userhash_new(void) | |
694 { | |
695 return th_calloc(1, sizeof(nn_userhash_t)); | |
696 } | |
697 | |
698 | |
699 int nn_userhash_insert(nn_userhash_t *list, const char *encname) | |
608 { | 700 { |
609 uint8_t hash; | 701 uint8_t hash; |
610 nn_user_t *user; | 702 nn_user_t *user; |
611 | 703 |
612 /* Check arguments */ | 704 /* Check arguments */ |
613 if (list == NULL || encname == NULL) | 705 if (list == NULL || encname == NULL) |
614 return -1; | 706 return -1; |
615 | 707 |
616 /* Check if list data exists */ | |
617 if (*list == NULL) { | |
618 *list = th_calloc(1, sizeof(nn_userhash_t)); | |
619 if (*list == NULL) | |
620 return -2; | |
621 } | |
622 | |
623 /* Check if username is already there */ | 708 /* Check if username is already there */ |
624 if (nn_user_find_enc(*list, encname) != NULL) | 709 if (nn_user_find_enc(list, encname) != NULL) |
625 return 1; | 710 return 1; |
626 | 711 |
627 /* No, we'll add it */ | 712 /* No, we'll add it */ |
628 if ((user = th_calloc(1, sizeof(nn_user_t))) == NULL) | 713 if ((user = th_calloc(1, sizeof(nn_user_t))) == NULL) |
629 return -3; | 714 return -3; |
632 user->name = nn_dbldecode_str(encname); | 717 user->name = nn_dbldecode_str(encname); |
633 if (user->encname == NULL || user->name == NULL) | 718 if (user->encname == NULL || user->name == NULL) |
634 return -4; | 719 return -4; |
635 | 720 |
636 hash = nn_hash_user(encname); | 721 hash = nn_hash_user(encname); |
637 nn_user_insert(&((*list)->buckets[hash]), user); | 722 nn_user_insert(&(list->buckets[hash]), user); |
723 | |
638 return 0; | 724 return 0; |
725 } | |
726 | |
727 | |
728 int nn_userhash_delete(nn_userhash_t *list, const char *encname) | |
729 { | |
730 uint8_t hash; | |
731 | |
732 /* Check arguments */ | |
733 if (list == NULL || encname == NULL) | |
734 return -1; | |
735 | |
736 /* Check if username is already there */ | |
737 hash = nn_hash_user(encname); | |
738 if (list->buckets[hash] != NULL) { | |
739 nn_user_t *curr, *prev; | |
740 curr = list->buckets[hash]; | |
741 prev = NULL; | |
742 while (curr != NULL) { | |
743 if (strcasecmp(curr->encname, encname) == 0) { | |
744 if (prev) | |
745 prev->next = curr->next; | |
746 else | |
747 list->buckets[hash] = curr->next; | |
748 | |
749 nn_user_free(curr); | |
750 | |
751 return 0; | |
752 } else { | |
753 prev = curr; | |
754 curr = curr->next; | |
755 } | |
756 } | |
757 } | |
758 | |
759 return 1; | |
639 } | 760 } |
640 | 761 |
641 | 762 |
642 nn_user_t *nn_user_copy(const nn_user_t *src) | 763 nn_user_t *nn_user_copy(const nn_user_t *src) |
643 { | 764 { |
656 | 777 |
657 return user; | 778 return user; |
658 } | 779 } |
659 | 780 |
660 | 781 |
661 static void nn_user_free(nn_user_t *user) | 782 void nn_user_free(nn_user_t *user) |
662 { | 783 { |
663 th_free(user->encname); | 784 th_free(user->encname); |
664 th_free(user->name); | 785 th_free(user->name); |
665 th_free(user); | 786 th_free(user); |
666 } | 787 } |
674 nn_user_free(curr); | 795 nn_user_free(curr); |
675 curr = next; | 796 curr = next; |
676 } | 797 } |
677 } | 798 } |
678 | 799 |
679 void nn_user_free_hash(nn_userhash_t *hash) | 800 void nn_userhash_free(nn_userhash_t *hash) |
680 { | 801 { |
681 int i; | 802 int i; |
682 if (hash == NULL) | 803 if (hash == NULL) |
683 return; | 804 return; |
684 | 805 |