Exemplo n.º 1
0
u32 File::WriteNewKey(const char *case_key, const char *key, int key_len, LineItem *front, LineItem *end)
{
	// Strip off dotted parts until we find it in the hash table
	for (int jj = key_len - 1; jj > 1; --jj)
	{
		// Search for next dot
		if (key[jj] != '.') continue;

		// Create a key from the parent part of the string
		u32 hash = MurmurHash(key, jj).Get32();

		// Look up the parent item
		LineItem *parent = _table.Lookup(KeyAdapter(key, jj, hash));
		if (parent)
		{
			// If parent is already enlisted,
			if (parent->_enlisted)
			{
				// Insert after parent
				end->_sort_next = parent->_sort_next;
				parent->_sort_next = front;
			}
			else
			{
				// NOTE: New items at end are all enlisted so will not get here with a new-item parent

				// Insert at front of the modified list
				end->_sort_next = _modded;
				_modded = front;
			}

			// Remember key depth
			_key_depth = parent->_depth;

			// Return end-of-line offset of parent
			return parent->_eol_offset ? parent->_eol_offset : parent->_sort_value;
		}
		else
		{
			// Create a hash table entry for this key
			LineItem *item = _table.Create(KeyAdapter(key, jj, hash));
			if (!item)
			{
				CAT_FATAL("Ragdoll") << "Out of memory";
				return 0;
			}

			// NOTE: Will not find this item as a parent during recursion
			// so leaving the item uninitialized for now is okay.

			// Recurse to find parent
			u32 offset = WriteNewKey(case_key, key, jj, item, end);

			// Go ahead and fill in the item
			item->_enlisted = true;
			item->_sort_value = offset;
			item->_eol_offset = 0; // Indicate it is a new item that needs new item processing
			item->_sort_next = front;
			item->_depth = ++_key_depth;
			item->_case_key.SetFromRangeString(case_key, jj);
			item->ClearValue();

			CAT_DEBUG_ENFORCE(_key_depth <= Parser::MAX_TAB_RECURSION_DEPTH);

			return offset;
		}
	}

	// Did not find the parent at all, so this is a completely new item

	// Insert at the front of the eof list
	end->_sort_next = _eof_head;
	_eof_head = front;

	// Remember key depth
	_key_depth = -1;

	return 0;
}
Exemplo n.º 2
0
int Parser::ReadTokens(int root_key_len, int root_depth)
{
	int eof = 0;

	do
	{
		// If there is not enough space to append the first token to the end of the root key,
		if (root_key_len + 1 + _first_len > MAX_CHARS)
		{
			// Signal EOF here to avoid mis-attributing keys
			CAT_WARN("Settings") << "Long line caused settings processing to abort early";
			return 0;
		}

		// Append first token to root key
		int key_len = root_key_len + _first_len;
		char *write_key = _root_key + root_key_len;

		if (root_key_len > 0)
		{
			_root_key[root_key_len] = '.';
			++write_key;
			++key_len;
		}

		memcpy(write_key, _first, _first_len);
		write_key[_first_len] = '\0';

		// Add this path to the hash table
		SanitizedKey san_key(_root_key, key_len);
		KeyAdapter key_input(san_key);
		LineItem *item = _output_file->_table.Lookup(key_input);
		if (!item)
		{
			// Create a new item for this key
			item = _output_file->_table.Create(key_input);

			if (!_is_override)
				item->_enlisted = false;
			else
			{
				// Push onto the new list
				CAT_FSLL_PUSH_FRONT(_output_file->_newest, item, _sort_next);
				item->_enlisted = true;

				item->_case_key.SetFromRangeString(_root_key, key_len);
			}
		}
		else
		{
			if (!item->_enlisted)
			{
				// Push onto the modded list
				CAT_FSLL_PUSH_FRONT(_output_file->_modded, item, _sort_next);
				item->_enlisted = true;
			}
		}

		// Update item value
		if (item)
		{
			if (!_is_override)
			{
				// Calculate key end offset and end of line offset
				u32 key_end_offset = (u32)(_first + _first_len - _file_front);
				u32 eol_offset;

				if (!_eol)
					eol_offset = (u32)(_eof - _file_front);
				else
					eol_offset = (u32)(_eol - _file_front);

				item->_sort_value = key_end_offset;
				item->_eol_offset = eol_offset;
			}

			item->_depth = _depth;

			// If second token is set,
			if (_second_len > 0)
				item->SetValueRangeStr(_second, _second_len);
			else
				item->ClearValue();
		}

		// For each line until EOF,
		eof = 0;
		int depth = _depth;
		while (NextLine())
		{
			// Skip blank lines
			if (_first_len == 0) continue;

			// If new line depth is at or beneath the root,
			if (root_depth >= _depth)
				eof = 1; // Pass it back to the root to handle
			// If new line is a child of current depth,
			else if (depth < _depth)
			{
				// Otherwise the new line depth is deeper, so recurse and add onto the key
				eof = ReadTokens(key_len, depth);

				// If not EOF,
				if (eof != 0)
				{
					// If new line depth is at the same level as current token,
					if (root_depth < _depth)
						eof = 2; // Repeat whole routine again at this depth
					else
						eof = 1; // Pass it back to the root to handle
				}
			}
			else // New line depth is at about the same level as current
				eof = 2; // Repeat whole routine again at this depth

			break;
		}

		// Remove appended token
		_root_key[root_key_len] = '\0';
	} while (eof == 2);

	return eof;
}