forked from fox0430/moe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgapbuffer.c
147 lines (118 loc) · 4.06 KB
/
gapbuffer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include"gapbuffer.h"
int gapBufferInit(gapBuffer* gb){
gb->buffer = (charArray**)malloc(sizeof(charArray*));
gb->size = 0;
gb->capacity = 1;
gb->gapBegin = 0;
gb->gapEnd = 1;
return 1;
}
int gapBufferReserve(gapBuffer* gb, int capacity){
if(capacity < gb->size || capacity <= 0){
printf("Gapbuffer: New buffer capacity is too small.\n");
return -1;
}
gapBufferMakeGap(gb, gb->capacity - (gb->gapEnd - gb->gapBegin));
charArray** newBuffer = (charArray**)realloc(gb->buffer, sizeof(charArray*)*capacity);
if(newBuffer == NULL){
printf("Gapbuffer: Cannot reallocate new memory.\n");
return -1;
}
gb->buffer = newBuffer;
gb->gapBegin = gb->size;
gb->gapEnd = capacity;
gb->capacity = capacity;
return 1;
}
// Create a gap starting with gapBegin
int gapBufferMakeGap(gapBuffer* gb,int gapBegin){
if(gapBegin < 0 || gb->capacity-gapBegin < gb->gapEnd-gb->gapBegin){
printf("Gapbuffer: Invalid position.\n");
return -1;
}
if(gapBegin < gb->gapBegin){
memmove(gb->buffer + (gb->gapEnd-gb->gapBegin+gapBegin), gb->buffer + gapBegin, sizeof(charArray*)*(gb->gapBegin-gapBegin));
}else{
int gapEnd = gapBegin + (gb->gapEnd-gb->gapBegin);
memmove(gb->buffer+gb->gapBegin, gb->buffer+gb->gapEnd, sizeof(charArray*)*(gapEnd-gb->gapEnd));
}
gb->gapEnd = gapBegin + (gb->gapEnd-gb->gapBegin);
gb->gapBegin = gapBegin;
return 1;
}
//insertedPositionの直前に要素を挿入する.末尾に追加したい場合はinsertedPositionにバッファの要素数を渡す.
//ex.空のバッファに要素を追加する場合はinsertedPositionに0を渡す.
int gapBufferInsert(gapBuffer* gb, charArray* element, int position){
if(position < 0 || gb->size < position){
printf("Gapbuffer: Invalid position.\n");
return -1;
}
if(gb->size == gb->capacity) gapBufferReserve(gb, gb->capacity*2);
if(gb->gapBegin != position) gapBufferMakeGap(gb, position);
gb->buffer[gb->gapBegin] = element;
++gb->gapBegin;
++gb->size;
return 1;
}
// Delete [begin,end] elements
int gapBufferDel(gapBuffer* gb, int begin, int end){
if(begin > end || begin < 0 || gb->size < end){
printf("Gapbuffer: Invalid interval.\n");
return -1;
}
int begin_ = gb->gapBegin > begin ? begin : gb->gapEnd + (begin - gb->gapBegin),
end_ = gb->gapBegin > end ? end : gb->gapEnd + (end - gb->gapBegin);
if(begin_ <= gb->gapBegin && gb->gapEnd <= end_){
for(int i = begin_; i < gb->gapBegin; ++i){
if(charArrayFree(gb->buffer[i]) == -1) return -1;
free(gb->buffer[i]);
}
for(int i = gb->gapEnd; i < end_; ++i){
if(charArrayFree(gb->buffer[i]) == -1) return -1;
free(gb->buffer[i]);
}
gb->gapBegin = begin_;
gb->gapEnd = end_;
}else if(end_ <= gb->gapBegin){
for(int i = begin_; i < end_; ++i){
if(charArrayFree(gb->buffer[i]) == -1) return -1;
free(gb->buffer[i]);
}
gapBufferMakeGap(gb, end_);
gb->gapBegin = begin_;
}else{
for(int i = begin_; i < end_; ++i){
if(charArrayFree(gb->buffer[i]) == -1) return -1;
free(gb->buffer[i]);
}
memmove(gb->buffer + gb->gapBegin, gb->buffer + gb->gapEnd, sizeof(charArray*)*(begin_ - gb->gapEnd));
gb->gapBegin = gb->gapBegin + begin_ - gb->gapEnd;
gb->gapEnd = end_;
}
gb->size -= end - begin;
while(gb->size > 0 && gb->size * 4 <= gb->capacity) if(gapBufferReserve(gb, gb->capacity / 2) == -1) return -1;
return 1;
}
charArray* gapBufferAt(gapBuffer* gb, int index){
if(index < 0 || gb->size <= index){
printf("Gapbuffer: Invalid index.\n");
exit(0);
}
if(index < gb->gapBegin) return gb->buffer[index];
return gb->buffer[gb->gapEnd+(index - gb->gapBegin)];
}
bool gapBufferIsEmpty(gapBuffer* gb){
return gb->capacity == gb->gapEnd - gb->gapBegin;
}
int gapBufferFree(gapBuffer* gb){
for(int i = 0; i < gb->gapBegin; ++i){
if(charArrayFree(gb->buffer[i]) == -1) return -1;
free(gb->buffer[i]);
}
for(int i = gb->gapEnd; i < gb->capacity; ++i){
if(charArrayFree(gb->buffer[i]) == -1) return -1;
free(gb->buffer[i]);
}
free(gb->buffer);
return 1;
}