OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / opencog / atoms / value / ContainerValue.cc

97 lines · cc ref:
/*
 * opencog/atoms/value/ContainerValue.cc
 *
 * Copyright (C) 2020, 2025 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/value/ContainerValue.h>

#include <sstream>

using namespace opencog;

// ==============================================================

std::string ContainerValue::to_string(const std::string& indent) const
{
	// The default printer for ContainerValue is LinkValue ...
	// with only one small problem: containers can block under certain
	// conditions.  This provides a non-blocking printer.
	//
	// The BLOCKING_SIG containers will hang if the container is open,
	// and the STREAMING_SIG containers will hang if the container is
	// empty.
	//
	// XXX FIXME, below is correct only for BLOCKING_SIG ...
	if (is_closed()) return LinkValue::to_string(indent);

	return indent + "(" + nameserver().getTypeName(get_type()) +
	   ") ;; open for writing";
}

// ==============================================================

bool ContainerValue::operator==(const Value& other) const
{
	if (this == &other) return true;

	if (not is_closed()) return false;
	if (other.is_type(CONTAINER_VALUE))
	{
		const ContainerValue* cvp = (const ContainerValue*) &other;
		if (not cvp->is_closed()) return false;
		// Why call update()? See comment below.
		cvp->update();
	}

	// The LinkValue::operator==() will fail unless data has been moved
	// from the container to the _value. The update() will do this
	// movement. Its safe to do now, too, since the container is closed.
	update();
	return LinkValue::operator==(other);
}

// ==============================================================

/// Provide override ordering for non-closed containers.
/// As currently implemented, this is not a stable ordering;
/// it will change when the container closes. This seems like
/// maybe a bad idea; on the other hand, we do want to get the
/// contentional lexicographic compare when they are closed.
/// So this is a confused mashup. Punt on a final decision to
/// some future date, when this becomes more clear.
///
/// Why is this a concern? Well, UnisetValues can contain *other*
/// (open) UnisetValues, and if we don't get this right, they get
/// deduplicated by accident.
bool ContainerValue::operator<(const Value& other) const
{
	if (this == &other) return false;

	if (not is_closed()) return this < &other;

	if (other.is_type(CONTAINER_VALUE) and
	    not ((const ContainerValue*) &other)->is_closed())
		return this < &other;

	return LinkValue::operator<(other);
}

// ==============================================================