/
LineBuffer.cpp
executable file
·266 lines (237 loc) · 9.36 KB
/
LineBuffer.cpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*
* MojoMerge -- A cross-platform compare-and-merge utility.
* Copyright (C) 2007 Ryan C. Gordon and Gregory S. Read.
*
* Please refer to LICENSE.txt in the root directory of the source
* distribution for licensing details.
*/
/* LineBuffer.cpp - Implementation of the LineBuffer class
*
*/
#include "LineBuffer.h"
using namespace MojoMerge;
LineBuffer::LineBuffer(const char *Buffer)
{
const char *p; // Pointer to current char in buffer
const char *StartP; // Pointer for start of line
char c; // Current character
uint32 CharCount; // Number of characters so far for new line
bool NewLine; // Should we create a new line?
// Set member default values
LineCount = 0;
Lines = NULL;
LinesAllocated = 0;
// Only do processing if they passed a buffer
if(Buffer != NULL)
{
// Set our pointers to the beginning of the buffer;
StartP = p = Buffer;
// Reset our CharCount value
CharCount = 0;
// No new line encountered yet
NewLine = false;
// Loop through the buffer until we hit a null terminator
while((c = *p) != 0x00)
{
// Increment our number of characters
CharCount++;
// If we detect a CR character
if(c == CR)
{
// Get the next character to see if it's a CR/LF combination
c = *(++p);
if(c == LF)
{
// We got a LF character, add to the character count
CharCount++;
// New line encountered (DOS style)
NewLine = true;
}
// Another character or null terminator encountered
else
{
// We got another character, that character is a part of
// next line, so we need to set our pointer back one.
p--;
// New line encountered (Mac style)
NewLine = true;
}
}
// If we detect a LF character
else if(c == LF)
{
// New line encountered (UNIX style)
NewLine = true;
}
// Go to next character
p++;
// If the NewLine flag is set
if(NewLine)
{
// Add a new line to our array
AddToLinesArray(StartP, CharCount);
// Set the start of the next line to our current position
StartP = p;
// Reset newline flag
NewLine = false;
// Reset our character count
CharCount = 0;
}
}
// If the last line did not have a newline character, we need to
// add that as the last line in the array
if(CharCount > 0)
AddToLinesArray(StartP, CharCount);
}
}
LineBuffer::~LineBuffer()
{
uint32 i;
// Deallocate each line in the lines array
for(i = 0; i < LineCount; i++)
delete Lines[i];
// Now delete the array
delete Lines;
}
void LineBuffer::MoveLinesTo(LineBuffer *DestBuffer, uint32 Start, uint32 End,
uint32 Dest)
{
uint32 LineCountToMove; // Number of lines being moved
char **NewLines; // New array for the destination
uint32 DestOriginalLineCount; // Line count of original dest buffer
uint32 SrcOriginalLineCount; // Line count of original source buffer
// Start has to be greater than 0
assert(Start > 0);
// End has to be less than or equal to the number of lines in the source
assert(End <= LineCount);
// Start has to be less than or equal to End
assert(Start <= End);
// Figure out how many lines we're moving
LineCountToMove = End - Start + 1;
// Retain original line count of src and dest buffers
SrcOriginalLineCount = LineCount;
DestOriginalLineCount = DestBuffer->LineCount;
// Increment the total line count for the destination
DestBuffer->LineCount += LineCountToMove;
// Decrement the total line count from the source
LineCount -= LineCountToMove;
// Allocate a new array to accomodate the lines being added plus allocate
// a little extra for later transactions.
DestBuffer->LinesAllocated = DestBuffer->LineCount + LINES_ARRAY_BLOCK;
// Perform memory allocation
NewLines = new char*[DestBuffer->LinesAllocated];
// Make sure allocation was successful
assert(NewLines != NULL);
// Copy the items from our original dest buffer before the index we're
// inserting to.
memcpy(NewLines, DestBuffer->Lines, Dest * sizeof(char *));
// Copy the items from our source (from the Start to End index) to our
// destination.
memcpy(&NewLines[Dest], &Lines[Start - 1], LineCountToMove * sizeof(char *));
// Copy the items from our original Dest buffer after the Dest index to our
// new buffer
memcpy(&NewLines[Dest + LineCountToMove], &DestBuffer->Lines[Dest],
(DestOriginalLineCount - Dest) * sizeof(char *));
// In source buffer, copy items from after the End index to the Start index
// and therefore overwritting the items that were moved.
memcpy(&Lines[Start - 1], &Lines[End], (SrcOriginalLineCount - End) * sizeof(char *));
// Delete original buffer
delete DestBuffer->Lines;
// Set it to our new buffer
DestBuffer->Lines = NewLines;
}
void LineBuffer::CopyLinesTo(LineBuffer *DestBuffer, uint32 Start, uint32 End,
uint32 Dest)
{
uint32 LineCountToCopy; // Number of lines being copied
char **NewLines; // New array for the destination
uint32 DestOriginalLineCount; // Line count of original dest buffer
char **pDest, **pSrc; // Temporary pointers for copying data
uint32 i; // Generic counter
// Start has to be greater than 0
assert(Start > 0);
// End has to be less than or equal to the number of lines in the source
assert(End <= LineCount);
// Start has to be less than or equal to End
assert(Start <= End);
// Dest has to be less than or equal to number of lines in dest buffer
assert(Dest <= DestBuffer->LineCount);
// Figure out how many lines we're copying
LineCountToCopy = End - Start + 1;
// Retain original line count of dest buffer
DestOriginalLineCount = DestBuffer->LineCount;
// Increment the total line count for the destination
DestBuffer->LineCount += LineCountToCopy;
// Allocate a new array to accomodate the lines being added plus allocate
// a little extra for later transactions.
DestBuffer->LinesAllocated = DestBuffer->LineCount + LINES_ARRAY_BLOCK;
// Perform memory allocation
NewLines = new char*[DestBuffer->LinesAllocated];
//NewLines = (char **)malloc(DestBuffer->LinesAllocated * sizeof(char *));
// Make sure allocation was successful
assert(NewLines != NULL);
// Copy the items from our original dest buffer before the index we're
// inserting to.
memcpy(NewLines, DestBuffer->Lines, Dest * sizeof(char *));
// Copy the items from our source (from the Start to End index) to our
// destination.
pDest = &NewLines[Dest];
pSrc = &Lines[Start - 1];
for(i = 0; i < LineCountToCopy; i++)
{
// Allocate for new string (size of source string + null terminator)
*pDest = new char[strlen(*pSrc) + 1];
// Make sure allocation was successful
assert(*pDest != NULL);
// Copy source string to destination string
strcpy(*pDest, *pSrc);
// Increment to next index in each array
pDest++;
pSrc++;
}
// Copy the items from our original Dest buffer after the Dest index to our
// new buffer
memcpy(&NewLines[Dest + LineCountToCopy], &DestBuffer->Lines[Dest],
(DestOriginalLineCount - Dest) * sizeof(char *));
// Delete original buffer
delete DestBuffer->Lines;
// Set it to our new buffer
DestBuffer->Lines = NewLines;
}
void LineBuffer::AddToLinesArray(const char *StartP, uint32 Length)
{
char *NewString; // New string added to lines array
// Increment the total line count
LineCount++;
// If we have to allocate more memory for the new line
if(LineCount > LinesAllocated)
{
// Add another "block" of lines to our allocated lines
LinesAllocated = LinesAllocated + LINES_ARRAY_BLOCK;
// Perform memory allocation while retaining data
Lines = (char **)realloc(Lines, LinesAllocated * sizeof(char *));
// Make sure allocation was successful
assert(Lines != NULL);
}
// Allocate new string based on specified length plus null terminator
NewString = new char[Length + 1];
// Make sure the allocate was successful
assert(NewString != NULL);
// Copy characters to new string
strncpy(NewString, StartP, Length);
// Add null terminator
NewString[Length] = 0x00;
// Add the string to the array (array is 0-based)
Lines[LineCount-1] = NewString;
}
const char *LineBuffer::GetLine(uint32 LineNumber)
{
// Make sure the LineNumber is within the array range
assert(LineNumber > 0 && LineNumber <= LineCount);
// Return requested line. Array is 0-based, but LineNumber is 1-based
return Lines[LineNumber - 1];
}
uint32 LineBuffer::GetLineCount()
{
return LineCount;
}