/**
{file:
    {name: LmiUpdatableLabel.h}
    {description: A class that creates a string label in a thread-safe manner.}
    {copyright:
    	(c) 2018 Vidyo, Inc.,
    	433 Hackensack Avenue,
    	Hackensack, NJ  07601.

    	All rights reserved.

    	The information contained herein is proprietary to Vidyo, Inc.
    	and shall not be reproduced, copied (in whole or in part), adapted,
    	modified, disseminated, transmitted, transcribed, stored in a retrieval
    	system, or translated into any language in any form by any means
    	without the express written consent of Vidyo, Inc.
    	                  ***** CONFIDENTIAL *****
    }
}
*/
#ifndef LMI_UPDATABLELABEL_H_
#define LMI_UPDATABLELABEL_H_

#include <Lmi/Utils/LmiStringList.h>
#include <Lmi/Os/LmiMutex.h>

/**
	{type:
		{name: LmiUpdatableLabel}
		{parent: Os}
		{include: Lmi/Os/LmiUpdatableLabel.h}
		{description: A debugging label for an object.  Its value can safely be updated without
			invalidating other threads' references to existing values for the label.}
	}
*/

typedef struct {
	LmiList(LmiString) labels;
	LmiMutex mutex;
} LmiUpdatableLabel;

/**
	{function:
		{name: LmiUpdatableLabelConstructDefault}
		{parent: LmiUpdatableLabel}
		{description: Construct an updatable label, with a value of the empty string.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelConstructDefault(LmiUpdatableLabel* l, LmiAllocator* a)}
		{parameter:
			{name: l}
			{description: The object to construct.}}
		{parameter:
			{name: a}
			{description: An allocator.}}
		{return: The constructed object, or NULL on failure.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelConstructDefault(LmiUpdatableLabel* l, LmiAllocator* a);


/**
	{function:
		{name: LmiUpdatableLabelConstruct}
		{parent: LmiUpdatableLabel}
		{description: Construct an updatable label, with an initial value.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelConstruct(LmiUpdatableLabel* l, const LmiString* initial, LmiAllocator* a)}
		{parameter:
			{name: l}
			{description: The updatable label to construct.}}
		{parameter:
			{name: initial}
			{description: The initial value of the label.}}
		{parameter:
			{name: a}
			{description: An allocator to use.}}
		{return: The constructed object, or NULL on failure.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelConstruct(LmiUpdatableLabel* l, const LmiString* initial, LmiAllocator* a);


/**
	{function:
		{name: LmiUpdatableLabelConstructCStr}
		{parent: LmiUpdatableLabel}
		{description: Construct an updatable label, with an initial value of C NUL-terminated string.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelConstructCStr(LmiUpdatableLabel* l, const char* initial, LmiAllocator* a)}
		{parameter:
			{name: l}
			{description: The object to construct.}}
		{parameter:
			{name: initial}
			{description: The initial value of the label.}}
		{parameter:
			{name: a}
			{description: An allocator to use.}}
		{return: The constructed object, or NULL on failure.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelConstructCStr(LmiUpdatableLabel* l, const char* initial, LmiAllocator* a);


/**
	{function:
		{name: LmiUpdatableLabelConstructFormatted}
		{parent: LmiUpdatableLabel}
		{description: Construct an updatable label, with an initial value that is a printf-formatted string.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelConstructFormatted(LmiUpdatableLabel* l, LmiAllocator* a, const char* fmt, ...)}
		{parameter:
			{name: l}
			{description: The object to construct.}}
		{parameter:
			{name: a}
			{description: An allocator to use}}
		{parameter:
			{name: fmt}
			{description: The printf-style format for the initial value.}}
		{parameter:
			{name: ...}
			{description: The arguments to {italic:fmt}.}}
		{return: The constructed object, or NULL on failure.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelConstructFormatted(LmiUpdatableLabel* l, LmiAllocator* a, const char* fmt, ...)  LmiFunctionPrintfLike(3, 4);


/**
	{function:
		{name: LmiUpdatableLabelConstructVFormatted}
		{parent: LmiUpdatableLabel}
		{description: Construct an updatable label, with an initial value that is a vprintf-formatted string.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelConstructVFormatted(LmiUpdatableLabel* l, LmiAllocator* a, const char* fmt, va_list args)}
		{parameter:
			{name: l}
			{description: The object to construct.}}
		{parameter:
			{name: a}
			{description: An allocator to use.}}
		{parameter:
			{name: fmt}
			{description: The vprintf-style format for the initial value.}}
		{parameter:
			{name: args}
			{description: The arguments to {italic:fmt}, as constructed by the functions of <stdarg.h>.}}
		{return: The constructed object, or NULL on failure.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelConstructVFormatted(LmiUpdatableLabel* l, LmiAllocator* a, const char* fmt, va_list args)  LmiFunctionVPrintfLike(3);


/**
	{function:
		{name: LmiUpdatableLabelConstructCopy}
		{parent: LmiUpdatableLabel}
		{description: Construct an updatable label, as a copy of an existing one.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelConstructCopy(LmiUpdatableLabel* l, const LmiUpdatableLabel* o)}
		{parameter:
			{name: l}
			{description: The object to construct.}}
		{parameter:
			{name: o}
			{description: The initial value of the label.}}
		{return: The constructed object, or NULL on failure.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelConstructCopy(LmiUpdatableLabel* l, const LmiUpdatableLabel* o);


/**
	{function:
		{name: LmiUpdatableLabelAssign}
		{parent: LmiUpdatableLabel}
		{description: Assign an updatable label as a copy of an existing one.}
		{prototype: LmiUpdatableLabel* LmiUpdatableLabelAssign(LmiUpdatableLabel* l, const LmiUpdatableLabel* o)}
		{parameter:
			{name: l}
			{description: The object to assign a value to.}}
		{parameter:
			{name: o}
			{description: The existing object.}}
		{return: The assigned-to object, or NULL on failure.}
		{note: Previous labels retrieved from this object are still valid.}
	}
*/
LmiUpdatableLabel* LmiUpdatableLabelAssign(LmiUpdatableLabel* l, const LmiUpdatableLabel* o);


/**
	{function:
		{name: LmiUpdatableLabelDestruct}
		{parent: LmiUpdatableLabel}
		{description: Destruct an updatable label.}
		{prototype: void LmiUpdatableLabelDestruct(LmiUpdatableLabel* l)}
		{parameter:
			{name: l}
			{description: The object to destruct.}}
	}
*/
void LmiUpdatableLabelDestruct(LmiUpdatableLabel* l);


/**
	{function:
		{name: LmiUpdatableLabelSet}
		{parent: LmiUpdatableLabel}
		{description: Set the value of an updatable label.}
		{prototype: LmiBool LmiUpdatableLabelSet(LmiUpdatableLabel* l, const LmiString* val)}
		{parameter:
			{name: l}
			{description: The label whose value to set.}}
		{parameter:
			{name: val}
			{description: The new value of the label.}}
		{return: LMI_TRUE on success, else LMI_FALSE.}
	}
*/
LmiBool LmiUpdatableLabelSet(LmiUpdatableLabel* l, const LmiString* val);


/**
	{function:
		{name: LmiUpdatableLabelSetCStr}
		{parent: LmiUpdatableLabel}
		{description: Set the value of an updatable label, as a C NUL-terminated string.}
		{prototype: LmiBool LmiUpdatableLabelSetCStr(LmiUpdatableLabel* l, const char* val)}
		{parameter:
			{name: l}
			{description: The label whose value to set.}}
		{parameter:
			{name: val}
			{description: The new value of the label, as a C NUL-terminated string.}}
		{return: LMI_TRUE on success, else LMI_FALSE.}
	}
*/
LmiBool LmiUpdatableLabelSetCStr(LmiUpdatableLabel* l, const char* val);


/**
	{function:
		{name: LmiUpdatableLabelSetFormatted}
		{parent: LmiUpdatableLabel}
		{description: Set the value of an updatable label, as a printf-formatted string.}
		{prototype: LmiBool LmiUpdatableLabelSetFormatted(LmiUpdatableLabel* l, const char* fmt, ...)}
		{parameter:
			{name: l}
			{description: The label whose value to set.}}
		{parameter:
			{name: fmt}
			{description: The printf-style format for the value.}}
		{parameter:
			{name: ...}
			{description: The arguments to {italic:fmt}.}}
		{return: LMI_TRUE on success, else LMI_FALSE.}
	}
*/
LmiBool LmiUpdatableLabelSetFormatted(LmiUpdatableLabel* l, const char* fmt, ...) LmiFunctionPrintfLike(2, 3);


/**
	{function:
		{name: LmiUpdatableLabelSetVFormatted}
		{parent: LmiUpdatableLabel}
		{description: Set the value of an updatable label, as a vprintf-formatted string.}
		{prototype: LmiBool LmiUpdatableLabelSetVFormatted(LmiUpdatableLabel* l, const char* fmt, va_list args)}
		{parameter:
			{name: l}
			{description: The label whose value to set.}}
		{parameter:
			{name: fmt}
			{description: The vprintf-style format for the value.}}
		{parameter:
			{name: args}
			{description: The arguments to {italic:fmt}, as constructed by the functions of <stdarg.h>.}}
		{return: LMI_TRUE on success, else LMI_FALSE.}
	}
*/
LmiBool LmiUpdatableLabelSetVFormatted(LmiUpdatableLabel* l, const char* fmt, va_list args) LmiFunctionVPrintfLike(2);


/**
	{function:
		{name: LmiUpdatableLabelGetCStr}
		{parent: LmiUpdatableLabel}
		{description: Get the current value of an updatable label, as a C NUL-terminated string.}
		{prototype: const char* LmiUpdatableLabelGetCStr(const LmiUpdatableLabel* l)}
		{parameter:
			{name: l}
			{description: The label whose value to get.}}
		{return: The value, as a NUL-terminated string.}
		{note: The returned value will be valid and unchanged until the updatable label is destructed, even if the label's value is subsequently updated.}
	}
*/
LMI_INLINE_DECLARATION const char* LmiUpdatableLabelGetCStr(const LmiUpdatableLabel* l);


/**
	{function:
		{name: LmiUpdatableLabelGetStr}
		{parent: LmiUpdatableLabel}
		{description: Get the current value of an updatable label, as an LmiString.}
		{prototype: const LmiString* LmiUpdatableLabelGetStr(const LmiUpdatableLabel* l)}
		{parameter:
			{name: l}
			{description: The label whose value to get.}}
		{return: The value, as an LmiString.}
		{note: The returned object will be valid and unchanged until the updatable label is destructed, even if the label's value is subsequently updated.}
	}
*/
LMI_INLINE_DECLARATION const LmiString* LmiUpdatableLabelGetStr(const LmiUpdatableLabel* l);


/**
	{function:
		{name: LmiUpdatableLabelGetAllocator}
		{parent: LmiUpdatableLabel}
		{description: Get the allocator associated with an updatable label.}
		{prototype: LmiAllocator* LmiUpdatableLabelGetAllocator(const LmiUpdatableLabel* l)}
		{parameter:
			{name: l}
			{description: The label whose allocator to get.}}
		{return: The updatable label.}
	}
*/
LMI_INLINE_DECLARATION LmiAllocator* LmiUpdatableLabelGetAllocator(const LmiUpdatableLabel* l);


#if LMI_INLINE_NEED_HEADER_FILE_DEFINITIONS
#include <Lmi/Os/LmiUpdatableLabelInline.h>
#endif

#endif /* LMI_UPDATABLELABEL_H_ */
