1/*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "AbbreviationTable.h"
7
8#include <stdio.h>
9
10#include <new>
11
12
13AbbreviationTable::AbbreviationTable(off_t offset)
14	:
15	fOffset(offset),
16	fData(NULL),
17	fSize(0)
18{
19}
20
21
22AbbreviationTable::~AbbreviationTable()
23{
24}
25
26
27status_t
28AbbreviationTable::Init(const void* section, off_t sectionSize)
29{
30	if (fOffset < 0 || fOffset >= sectionSize)
31		return B_BAD_DATA;
32
33	fData = (uint8*)section + fOffset;
34	fSize = sectionSize - fOffset;
35		// That's only the maximum size. Will be adjusted at the end.
36
37	status_t error = fEntryTable.Init();
38	if (error != B_OK)
39		return error;
40
41	DataReader abbrevReader(fData, fSize, 4);
42		// address size doesn't matter here
43
44	while (true) {
45		bool nullEntry;
46		status_t error = _ParseAbbreviationEntry(abbrevReader, nullEntry);
47		if (error != B_OK)
48			return error;
49
50		if (nullEntry)
51			break;
52	}
53
54	fSize -= abbrevReader.BytesRemaining();
55
56	return B_OK;
57}
58
59
60bool
61AbbreviationTable::GetAbbreviationEntry(uint32 code, AbbreviationEntry& entry)
62{
63	AbbreviationTableEntry* tableEntry = fEntryTable.Lookup(code);
64	if (tableEntry == NULL)
65		return false;
66
67	entry.SetTo(code, fData + tableEntry->offset, tableEntry->size);
68	return true;
69}
70
71
72status_t
73AbbreviationTable::_ParseAbbreviationEntry(DataReader& abbrevReader,
74	bool& _nullEntry)
75{
76	uint32 code = abbrevReader.ReadUnsignedLEB128(0);
77	if (code == 0) {
78		if (abbrevReader.HasOverflow()) {
79			fprintf(stderr, "Invalid abbreviation table 1!\n");
80			return B_BAD_DATA;
81		}
82		_nullEntry = true;
83		return B_OK;
84	}
85
86	off_t remaining = abbrevReader.BytesRemaining();
87
88/*	uint32 tag =*/ abbrevReader.ReadUnsignedLEB128(0);
89/*	uint8 hasChildren =*/ abbrevReader.Read<uint8>(DW_CHILDREN_no);
90
91//	printf("entry: %lu, tag: %lu, children: %d\n", code, tag,
92//		hasChildren);
93
94	// parse attribute specifications
95	while (true) {
96		uint32 attributeName = abbrevReader.ReadUnsignedLEB128(0);
97		uint32 attributeForm = abbrevReader.ReadUnsignedLEB128(0);
98		if (abbrevReader.HasOverflow()) {
99			fprintf(stderr, "Invalid abbreviation table 2!\n");
100			return B_BAD_DATA;
101		}
102
103		if (attributeName == 0 && attributeForm == 0)
104			break;
105
106//		printf("  attr: name: %lu, form: %lu\n", attributeName,
107//			attributeForm);
108	}
109
110	// create the entry
111	if (fEntryTable.Lookup(code) == NULL) {
112		AbbreviationTableEntry* entry = new(std::nothrow)
113			AbbreviationTableEntry(code, fSize - remaining,
114				remaining - abbrevReader.BytesRemaining());
115		if (entry == NULL)
116			return B_NO_MEMORY;
117
118		fEntryTable.Insert(entry);
119	} else {
120		fprintf(stderr, "Duplicate abbreviation table entry %" B_PRIu32 "!\n",
121			code);
122	}
123
124	_nullEntry = false;
125	return B_OK;
126}
127