in src/scripts/mdExts.js [922:1100]
function __MakeTableVisualizer(type)
{
class __TableVisualizer
{
get Database()
{
return this.m_database;
}
get Size()
{
return this.m_row_count;
}
getDimensionality()
{
return 1;
}
getValueAt(index)
{
if (type != "undefined")
{
return eval("new " + type + "(this, index)");
}
// For an untyped table, return values as arrays
var result = new Array();
var ptr = this.m_data.add(index * this.m_row_size);
for (var i = 0; i < this.m_columns.Count(); ++i)
{
var dataSize = this.m_columns[index].size;
var dataPtr = ptr.add(this.m_columns[i].offset);
var value = host.memory.readMemoryValues(dataPtr.address, 1, dataSize)[0];
result.push(value);
}
return result;
}
*[Symbol.iterator]()
{
var ptr = this.m_data;
for (var i = 0; i < this.m_row_count; ++i)
{
yield new host.indexedValue(this.getValueAt(i), [i]);
}
}
getValue(row, col)
{
if (row >= this.m_row_count)
{
throw new RangeError("Row index out of range: " + row);
}
else if (col >= this.m_columns.Count())
{
throw new RangeError("Column index out of range: " + col);
}
var dataSize = this.m_columns[col].size;
var ptr = this.m_data.add(row * this.m_row_size + this.m_columns[col].offset);
return host.memory.readMemoryValues(ptr.address, 1, dataSize)[0];
}
__lowerBound(col, value, min, max)
{
// First value that is not less than value
min = min || 0;
max = max || this.Size;
while (min < max)
{
var mid = Math.floor((min + max) / 2);
var testValue = this.getValue(mid, col);
if (testValue < value)
{
min = mid + 1;
}
else
{
max = mid;
}
}
return min;
}
__upperBound(col, value, min, max)
{
// First value that is greater than value
min = min || 0;
max = max || this.Size;
while (min < max)
{
var mid = Math.floor((min + max) / 2);
var testValue = this.getValue(mid, col);
if (testValue <= value)
{
min = mid + 1;
}
else
{
max = mid;
}
}
return min;
}
__equalRange(col, value, min, max)
{
var begin = this.__lowerBound(col, value, min, max);
var end = this.__upperBound(col, value, begin, max);
return new __TableRange(this, begin, end);
}
__fromCodedIndex(codedIndex, codedEnum)
{
var typeIndex = __codedValueType(codedIndex, codedEnum);
if (typeIndex >= codedEnum.Values.length)
{
throw new RangeError("Invalid " + codedEnum.Name + " coded index: " + typeIndex);
}
var target = codedEnum.Values[typeIndex];
if (target === null)
{
throw new RangeError("Invalid " + codedEnum.Name + " coded index: " + typeIndex);
}
var table = this.Database[target];
var row = __codedValueIndex(codedIndex, codedEnum);
if (row == -1)
{
return null;
}
return eval("new __" + target + "Visualizer(table, row)");
}
__getCodedIndex(row, col, codedEnum)
{
return this.__fromCodedIndex(this.getValue(row, col), codedEnum);
}
__getList(tableName, row, col)
{
// Lists are stored as a single index in the current row. This marks the beginning of the list. The next row in
// the current table is the index of one past our end
var table = this.Database[tableName];
var begin = this.getValue(row, col);
var end = table.Size;
if (row + 1 < this.Size)
{
end = this.getValue(row + 1, col);
}
return new __TableRange(table, begin - 1, end - 1);
}
__getTargetRow(tableName, row, col)
{
return this.Database[tableName][this.getValue(row, col) - 1];
}
__getParentRow(tableName, row, col)
{
// The parent references the first row in this table that belongs to its list. Thus, we need to look for the
// first value in the parent's table that references a later value in this table and then choose the previous
var table = this.Database[tableName];
var index = table.__upperBound(col, row + 1) - 1;
return table[index];
}
}
return __TableVisualizer;
}