1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "FileSourceCode.h"
8
9#include <string.h>
10
11#include "LocatableFile.h"
12#include "SourceFile.h"
13#include "SourceLanguage.h"
14#include "SourceLocation.h"
15
16
17FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile,
18	SourceLanguage* language)
19	:
20	fLock("source code"),
21	fFile(file),
22	fSourceFile(sourceFile),
23	fLanguage(language)
24{
25	fFile->AcquireReference();
26	fSourceFile->AcquireReference();
27	fLanguage->AcquireReference();
28}
29
30
31FileSourceCode::~FileSourceCode()
32{
33	fLanguage->ReleaseReference();
34	fSourceFile->ReleaseReference();
35	fFile->ReleaseReference();
36}
37
38
39status_t
40FileSourceCode::Init()
41{
42	return fLock.InitCheck();
43}
44
45
46status_t
47FileSourceCode::AddSourceLocation(const SourceLocation& location)
48{
49	// Find the insertion index; don't insert twice.
50	bool foundMatch;
51	int32 index = _FindSourceLocationIndex(location, foundMatch);
52	if (foundMatch)
53		return B_OK;
54
55	return fSourceLocations.Insert(location, index) ? B_OK : B_NO_MEMORY;
56}
57
58
59bool
60FileSourceCode::Lock()
61{
62	return fLock.Lock();
63}
64
65
66void
67FileSourceCode::Unlock()
68{
69	fLock.Unlock();
70}
71
72
73SourceLanguage*
74FileSourceCode::GetSourceLanguage() const
75{
76	return fLanguage;
77}
78
79
80int32
81FileSourceCode::CountLines() const
82{
83	return fSourceFile->CountLines();
84}
85
86
87const char*
88FileSourceCode::LineAt(int32 index) const
89{
90	return fSourceFile->LineAt(index);
91}
92
93
94int32
95FileSourceCode::LineLengthAt(int32 index) const
96{
97	return fSourceFile->LineLengthAt(index);
98}
99
100
101bool
102FileSourceCode::GetStatementLocationRange(const SourceLocation& location,
103	SourceLocation& _start, SourceLocation& _end) const
104{
105	int32 lineCount = CountLines();
106	if (location.Line() >= lineCount)
107		return false;
108
109	bool foundMatch;
110	int32 index = _FindSourceLocationIndex(location, foundMatch);
111
112	if (!foundMatch) {
113		if (index == 0)
114			return false;
115		index--;
116	}
117
118	_start = fSourceLocations[index];
119	_end = index + 1 < lineCount
120		? fSourceLocations[index + 1] : SourceLocation(lineCount);
121	return true;
122}
123
124
125LocatableFile*
126FileSourceCode::GetSourceFile() const
127{
128	return fFile;
129}
130
131
132int32
133FileSourceCode::_FindSourceLocationIndex(const SourceLocation& location,
134	bool& _foundMatch) const
135{
136	int32 lower = 0;
137	int32 upper = fSourceLocations.Size();
138	while (lower < upper) {
139		int32 mid = (lower + upper) / 2;
140		if (location <= fSourceLocations[mid])
141			upper = mid;
142		else
143			lower = mid + 1;
144	}
145
146	_foundMatch = lower < fSourceLocations.Size()
147		&& location == fSourceLocations[lower];
148	return lower;
149}
150