| 309 |
return (p_block->articles + (index % ARTICLE_PER_BLOCK)); |
return (p_block->articles + (index % ARTICLE_PER_BLOCK)); |
| 310 |
} |
} |
| 311 |
|
|
| 312 |
SECTION_LIST *section_list_create(const char *sname, const char *stitle, const char *master_name) |
SECTION_LIST *section_list_create(int32_t sid, const char *sname, const char *stitle, const char *master_name) |
| 313 |
{ |
{ |
| 314 |
SECTION_LIST *p_section; |
SECTION_LIST *p_section; |
| 315 |
|
|
| 343 |
|
|
| 344 |
p_section = p_section_list_pool + section_list_count; |
p_section = p_section_list_pool + section_list_count; |
| 345 |
|
|
| 346 |
|
p_section->sid = sid; |
| 347 |
|
|
| 348 |
strncpy(p_section->sname, sname, sizeof(p_section->sname - 1)); |
strncpy(p_section->sname, sname, sizeof(p_section->sname - 1)); |
| 349 |
p_section->sname[sizeof(p_section->sname - 1)] = '\0'; |
p_section->sname[sizeof(p_section->sname - 1)] = '\0'; |
| 350 |
|
|
| 532 |
p_section->p_article_tail = p_article; |
p_section->p_article_tail = p_article; |
| 533 |
|
|
| 534 |
// Update page |
// Update page |
| 535 |
if (p_article->visible && p_section->last_page_visible_article_count % BBS_article_limit_per_page == 0) |
if ((p_article->visible && p_section->last_page_visible_article_count % BBS_article_limit_per_page == 0) || |
| 536 |
|
p_section->article_count == 1) |
| 537 |
{ |
{ |
| 538 |
p_section->p_page_first_article[p_section->page_count] = p_article; |
p_section->p_page_first_article[p_section->page_count] = p_article; |
| 539 |
p_section->page_count++; |
p_section->page_count++; |
| 613 |
return affected_count; |
return affected_count; |
| 614 |
} |
} |
| 615 |
|
|
| 616 |
ARTICLE *section_list_find_article_with_offset(SECTION_LIST *p_section, int32_t aid, int32_t *p_page, int32_t *p_offset) |
ARTICLE *section_list_find_article_with_offset(SECTION_LIST *p_section, int32_t aid, int32_t *p_page, int32_t *p_offset, ARTICLE **pp_next) |
| 617 |
{ |
{ |
| 618 |
ARTICLE *p_article; |
ARTICLE *p_article; |
| 619 |
int left; |
int left; |
| 622 |
|
|
| 623 |
*p_page = -1; |
*p_page = -1; |
| 624 |
*p_offset = -1; |
*p_offset = -1; |
| 625 |
|
*pp_next = NULL; |
| 626 |
|
|
| 627 |
if (p_section == NULL) |
if (p_section == NULL) |
| 628 |
{ |
{ |
| 667 |
p_article = p_section->p_page_first_article[*p_page]; |
p_article = p_section->p_page_first_article[*p_page]; |
| 668 |
|
|
| 669 |
// p_section->p_page_first_article[*p_page]->aid <= aid < p_section->p_page_first_article[*p_page + 1]->aid |
// p_section->p_page_first_article[*p_page]->aid <= aid < p_section->p_page_first_article[*p_page + 1]->aid |
| 670 |
right = (*p_page == p_section->page_count - 1 ? INT32_MAX : p_section->p_page_first_article[*p_page + 1]->aid); |
right = (*p_page == MAX(0, p_section->page_count - 1) ? INT32_MAX : p_section->p_page_first_article[*p_page + 1]->aid); |
| 671 |
|
|
| 672 |
// left will be the offset of article found or offset to insert |
// left will be the offset of article found or offset to insert |
| 673 |
left = 0; |
left = 0; |
| 674 |
|
|
| 675 |
while (1) |
while (aid > p_article->aid) |
| 676 |
{ |
{ |
| 677 |
if (aid == p_article->aid) // found |
p_article = p_article->p_next; |
| 678 |
{ |
left++; |
| 679 |
break; |
|
| 680 |
} |
if (aid == p_article->aid) |
|
else if (aid < p_article->aid) // not exist |
|
| 681 |
{ |
{ |
| 682 |
p_article = NULL; |
*pp_next = p_article->p_next; |
| 683 |
break; |
break; |
| 684 |
} |
} |
| 685 |
|
|
|
// aid > p_article->aid |
|
|
p_article = p_article->p_next; |
|
|
left++; |
|
|
|
|
| 686 |
// over last article in the page |
// over last article in the page |
| 687 |
if (p_article == p_section->p_article_head || p_article->aid >= right) |
if (p_article == p_section->p_article_head || p_article->aid >= right) |
| 688 |
{ |
{ |
| 689 |
p_article = NULL; |
*pp_next = (p_article == p_section->p_article_head ? p_section->p_article_head : p_section->p_page_first_article[*p_page + 1]); |
| 690 |
break; |
*p_offset = left; |
| 691 |
|
return NULL; // not found |
| 692 |
} |
} |
| 693 |
} |
} |
| 694 |
|
|
| 695 |
|
if (aid < p_article->aid) |
| 696 |
|
{ |
| 697 |
|
*pp_next = p_article; |
| 698 |
|
p_article = NULL; // not found |
| 699 |
|
} |
| 700 |
|
else // aid == p_article->aid |
| 701 |
|
{ |
| 702 |
|
*pp_next = p_article->p_next; |
| 703 |
|
} |
| 704 |
|
|
| 705 |
*p_offset = left; |
*p_offset = left; |
| 706 |
|
|
| 707 |
return p_article; |
return p_article; |
| 710 |
int section_list_calculate_page(SECTION_LIST *p_section, int32_t start_aid) |
int section_list_calculate_page(SECTION_LIST *p_section, int32_t start_aid) |
| 711 |
{ |
{ |
| 712 |
ARTICLE *p_article; |
ARTICLE *p_article; |
| 713 |
|
ARTICLE *p_next; |
| 714 |
int32_t page; |
int32_t page; |
| 715 |
int32_t offset; |
int32_t offset; |
| 716 |
int visible_article_count; |
int visible_article_count; |
| 722 |
return -1; |
return -1; |
| 723 |
} |
} |
| 724 |
|
|
| 725 |
p_article = section_list_find_article_with_offset(p_section, start_aid, &page, &offset); |
if (p_section->article_count == 0) // empty |
| 726 |
if (p_article == NULL) |
{ |
| 727 |
|
p_section->page_count = 0; |
| 728 |
|
p_section->last_page_visible_article_count = 0; |
| 729 |
|
|
| 730 |
|
return 0; |
| 731 |
|
} |
| 732 |
|
|
| 733 |
|
if (start_aid > 0) |
| 734 |
{ |
{ |
| 735 |
if (page < 0) |
p_article = section_list_find_article_with_offset(p_section, start_aid, &page, &offset, &p_next); |
| 736 |
|
if (p_article == NULL) |
| 737 |
{ |
{ |
| 738 |
return 0; |
if (page < 0) |
| 739 |
|
{ |
| 740 |
|
return -1; |
| 741 |
|
} |
| 742 |
|
log_error("section_list_calculate_page() aid = %d not found in section sid = %d\n", |
| 743 |
|
start_aid, p_section->sid); |
| 744 |
|
return -2; |
| 745 |
} |
} |
| 746 |
|
|
| 747 |
log_error("section_list_calculate_page() aid = %d not found in section sid = %d\n", start_aid, p_section->sid); |
if (offset > 0) |
| 748 |
|
{ |
| 749 |
|
p_article = p_section->p_page_first_article[page]; |
| 750 |
|
} |
| 751 |
} |
} |
| 752 |
|
else |
|
if (offset > 0) |
|
| 753 |
{ |
{ |
| 754 |
p_article = p_section->p_page_first_article[page]; |
p_article = p_section->p_article_head; |
| 755 |
|
page = 0; |
| 756 |
|
offset = 0; |
| 757 |
} |
} |
| 758 |
|
|
| 759 |
visible_article_count = 0; |
visible_article_count = 0; |
| 799 |
|
|
| 800 |
return 0; |
return 0; |
| 801 |
} |
} |
| 802 |
|
|
| 803 |
|
int section_list_count_of_topic_articles(int32_t aid) |
| 804 |
|
{ |
| 805 |
|
ARTICLE *p_article; |
| 806 |
|
int article_count; |
| 807 |
|
|
| 808 |
|
p_article = article_block_find_by_aid(aid); |
| 809 |
|
if (p_article == NULL) |
| 810 |
|
{ |
| 811 |
|
return 0; // Not found |
| 812 |
|
} |
| 813 |
|
|
| 814 |
|
article_count = 0; |
| 815 |
|
|
| 816 |
|
do |
| 817 |
|
{ |
| 818 |
|
article_count++; |
| 819 |
|
p_article = p_article->p_topic_next; |
| 820 |
|
} while (p_article->aid != aid); |
| 821 |
|
|
| 822 |
|
return article_count; |
| 823 |
|
} |
| 824 |
|
|
| 825 |
|
int section_list_move_topic(SECTION_LIST *p_section_src, SECTION_LIST *p_section_dest, int32_t aid) |
| 826 |
|
{ |
| 827 |
|
ARTICLE *p_article; |
| 828 |
|
ARTICLE *p_next; |
| 829 |
|
int32_t page; |
| 830 |
|
int32_t offset; |
| 831 |
|
int32_t move_article_count; |
| 832 |
|
int32_t dest_article_count_old; |
| 833 |
|
int32_t last_unaffected_aid_src; |
| 834 |
|
|
| 835 |
|
if (p_section_dest == NULL) |
| 836 |
|
{ |
| 837 |
|
log_error("section_list_move_topic() NULL pointer error\n"); |
| 838 |
|
return -1; |
| 839 |
|
} |
| 840 |
|
|
| 841 |
|
if ((p_article = section_list_find_article_with_offset(p_section_src, aid, &page, &offset, &p_next)) == NULL) |
| 842 |
|
{ |
| 843 |
|
log_error("section_list_move_topic() error: article %d not found in section %d\n", aid, p_section_src->sid); |
| 844 |
|
return -2; |
| 845 |
|
} |
| 846 |
|
|
| 847 |
|
if (p_article->tid != 0) |
| 848 |
|
{ |
| 849 |
|
log_error("section_list_move_topic(aid = %d) error: article is not head of topic, tid = %d\n", aid, p_article->tid); |
| 850 |
|
return -2; |
| 851 |
|
} |
| 852 |
|
|
| 853 |
|
last_unaffected_aid_src = (p_article == p_section_src->p_article_head ? 0 : p_article->p_prior->aid); |
| 854 |
|
|
| 855 |
|
move_article_count = section_list_count_of_topic_articles(aid); |
| 856 |
|
if (move_article_count <= 0) |
| 857 |
|
{ |
| 858 |
|
log_error("section_list_count_of_topic_articles(aid = %d) <= 0\n", aid); |
| 859 |
|
return -2; |
| 860 |
|
} |
| 861 |
|
|
| 862 |
|
if (p_section_dest->article_count + move_article_count > BBS_article_limit_per_section) |
| 863 |
|
{ |
| 864 |
|
log_error("section_list_move_topic() error: article_count %d reach limit in section %d\n", |
| 865 |
|
p_section_dest->article_count + move_article_count, p_section_dest->sid); |
| 866 |
|
return -3; |
| 867 |
|
} |
| 868 |
|
|
| 869 |
|
dest_article_count_old = p_section_dest->article_count; |
| 870 |
|
|
| 871 |
|
do |
| 872 |
|
{ |
| 873 |
|
if (section_list_find_article_with_offset(p_section_dest, p_article->aid, &page, &offset, &p_next) != NULL) |
| 874 |
|
{ |
| 875 |
|
log_error("section_list_move_topic() error: article %d already in section %d\n", p_article->aid, p_section_dest->sid); |
| 876 |
|
return -4; |
| 877 |
|
} |
| 878 |
|
|
| 879 |
|
// Remove from bi-directional article list of src section |
| 880 |
|
if (p_section_src->p_article_head == p_article) |
| 881 |
|
{ |
| 882 |
|
p_section_src->p_article_head = p_article->p_next; |
| 883 |
|
} |
| 884 |
|
if (p_section_src->p_article_tail == p_article) |
| 885 |
|
{ |
| 886 |
|
p_section_src->p_article_tail = p_article->p_prior; |
| 887 |
|
} |
| 888 |
|
if (p_section_src->p_article_head == p_article) // || p_section_src->p_article_tail == p_article |
| 889 |
|
{ |
| 890 |
|
p_section_src->p_article_head = NULL; |
| 891 |
|
p_section_src->p_article_tail = NULL; |
| 892 |
|
} |
| 893 |
|
|
| 894 |
|
p_article->p_prior->p_next = p_article->p_next; |
| 895 |
|
p_article->p_next->p_prior = p_article->p_prior; |
| 896 |
|
|
| 897 |
|
// Insert into bi-directional article list of dest section |
| 898 |
|
if (p_next == NULL) // empty section |
| 899 |
|
{ |
| 900 |
|
p_section_dest->p_article_head = p_article; |
| 901 |
|
p_section_dest->p_article_tail = p_article; |
| 902 |
|
p_article->p_prior = p_article; |
| 903 |
|
p_article->p_next = p_article; |
| 904 |
|
} |
| 905 |
|
else |
| 906 |
|
{ |
| 907 |
|
if (p_section_dest->p_article_head == p_next) |
| 908 |
|
{ |
| 909 |
|
if (p_article->aid < p_next->aid) |
| 910 |
|
{ |
| 911 |
|
p_section_dest->p_article_head = p_article; |
| 912 |
|
} |
| 913 |
|
else // p_article->aid > p_next->aid |
| 914 |
|
{ |
| 915 |
|
p_section_dest->p_article_tail = p_article; |
| 916 |
|
} |
| 917 |
|
} |
| 918 |
|
|
| 919 |
|
p_article->p_prior = p_next->p_prior; |
| 920 |
|
p_article->p_next = p_next; |
| 921 |
|
p_next->p_prior->p_next = p_article; |
| 922 |
|
p_next->p_prior = p_article; |
| 923 |
|
} |
| 924 |
|
|
| 925 |
|
// Update article / topic counter of src / desc section |
| 926 |
|
p_section_src->article_count--; |
| 927 |
|
p_section_dest->article_count++; |
| 928 |
|
if (p_article->tid == 0) |
| 929 |
|
{ |
| 930 |
|
p_section_src->topic_count--; |
| 931 |
|
p_section_dest->topic_count++; |
| 932 |
|
} |
| 933 |
|
|
| 934 |
|
// Update visible article / topic counter of src / desc section |
| 935 |
|
if (p_article->visible) |
| 936 |
|
{ |
| 937 |
|
p_section_src->visible_article_count--; |
| 938 |
|
p_section_dest->visible_article_count++; |
| 939 |
|
if (p_article->tid == 0) |
| 940 |
|
{ |
| 941 |
|
p_section_src->visible_topic_count--; |
| 942 |
|
p_section_dest->visible_topic_count++; |
| 943 |
|
} |
| 944 |
|
} |
| 945 |
|
|
| 946 |
|
// Update page for empty dest section |
| 947 |
|
if (p_section_dest->article_count == 1) |
| 948 |
|
{ |
| 949 |
|
p_section_dest->p_page_first_article[0] = p_article; |
| 950 |
|
p_section_dest->page_count = 1; |
| 951 |
|
p_section_dest->last_page_visible_article_count = (p_article->visible ? 1 : 0); |
| 952 |
|
} |
| 953 |
|
|
| 954 |
|
p_article = p_article->p_topic_next; |
| 955 |
|
} while (p_article->aid != aid); |
| 956 |
|
|
| 957 |
|
if (p_section_dest->article_count - dest_article_count_old != move_article_count) |
| 958 |
|
{ |
| 959 |
|
log_error("section_list_move_topic() error: count of moved articles %d != %d\n", |
| 960 |
|
p_section_dest->article_count - dest_article_count_old, move_article_count); |
| 961 |
|
} |
| 962 |
|
|
| 963 |
|
// Re-calculate pages of both src and desc sections |
| 964 |
|
if (section_list_calculate_page(p_section_src, last_unaffected_aid_src) < 0) |
| 965 |
|
{ |
| 966 |
|
log_error("section_list_calculate_page(section = %d, aid = %d) error at aid = %d\n", p_section_src->sid, last_unaffected_aid_src, aid); |
| 967 |
|
} |
| 968 |
|
if (section_list_calculate_page(p_section_dest, aid) < 0) |
| 969 |
|
{ |
| 970 |
|
log_error("section_list_calculate_page(section = %d, aid = %d) error\n", p_section_dest->sid, aid); |
| 971 |
|
} |
| 972 |
|
|
| 973 |
|
return move_article_count; |
| 974 |
|
} |