headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / debugger / files / SourceFile.cpp
blob63a0e8d20bddee64a20a056400a43f01e6bbf6c6
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "SourceFile.h"
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
16 #include <new>
19 static const int32 kMaxSourceFileSize = 10 * 1024 * 1024;
22 // #pragma mark - SourceFileOwner
25 SourceFileOwner::~SourceFileOwner()
30 // #pragma mark - SourceFile
33 SourceFile::SourceFile(SourceFileOwner* owner)
35 fOwner(owner),
36 fFileContent(NULL),
37 fLineOffsets(NULL),
38 fLineCount(0)
43 SourceFile::~SourceFile()
45 free(fFileContent);
46 delete[] fLineOffsets;
47 fOwner->SourceFileDeleted(this);
51 status_t
52 SourceFile::Init(const char* path)
54 // open the file
55 int fd = open(path, O_RDONLY);
56 if (fd < 0)
57 return errno;
59 // stat the file to get its size
60 struct stat st;
61 if (fstat(fd, &st) < 0) {
62 close(fd);
63 return errno;
66 if (st.st_size > kMaxSourceFileSize) {
67 close(fd);
68 return B_FILE_TOO_LARGE;
70 size_t fileSize = st.st_size;
72 if (fileSize == 0) {
73 close(fd);
74 return B_BAD_VALUE;
77 // allocate the content buffer
78 fFileContent = (char*)malloc(fileSize + 1);
79 // one more byte for a terminating null
80 if (fFileContent == NULL) {
81 close(fd);
82 return B_NO_MEMORY;
85 // read the file
86 ssize_t bytesRead = read(fd, fFileContent, fileSize);
87 close(fd);
88 if (bytesRead < 0 || (size_t)bytesRead != fileSize)
89 return bytesRead < 0 ? errno : B_FILE_ERROR;
91 // null-terminate
92 fFileContent[fileSize] = '\0';
94 // count lines
95 fLineCount = 1;
96 for (size_t i = 0; i < fileSize; i++) {
97 if (fFileContent[i] == '\n')
98 fLineCount++;
101 // allocate line offset array
102 fLineOffsets = new(std::nothrow) int32[fLineCount + 1];
103 if (fLineOffsets == NULL)
104 return B_NO_MEMORY;
106 // get the line offsets and null-terminate the lines
107 int32 lineIndex = 0;
108 fLineOffsets[lineIndex++] = 0;
109 for (size_t i = 0; i < fileSize; i++) {
110 if (fFileContent[i] == '\n') {
111 fFileContent[i] = '\0';
112 fLineOffsets[lineIndex++] = i + 1;
115 fLineOffsets[fLineCount] = fileSize + 1;
117 return B_OK;
121 int32
122 SourceFile::CountLines() const
124 return fLineCount;
128 const char*
129 SourceFile::LineAt(int32 index) const
131 return index >= 0 && index < fLineCount
132 ? fFileContent + fLineOffsets[index] : NULL;
136 int32
137 SourceFile::LineLengthAt(int32 index) const
139 return index >= 0 && index < fLineCount
140 ? fLineOffsets[index + 1] - fLineOffsets[index] - 1: 0;
143 void
144 SourceFile::LastReferenceReleased()
146 fOwner->SourceFileUnused(this);
147 delete this;