/**
{file:
    {name: LmiPath.h}
    {description: A class for creating, validating, manipulating paths.}
    {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_PATH_H
#define LMI_PATH_H

#include "Lmi/Utils/LmiString.h"
#include "Lmi/Utils/LmiStringVector.h"

/**
{type:
	{name: LmiPath}
	{parent: Os}
	{include: Lmi/Os/LmiPath.h}
	{description:
		{p:Represents a file system path.  LmiPath is an alias of LmiString and provides an alternative
		interface to LmiString to make it easier and safer to manipulate file system paths.  Therefore, LmiPath
		objects and LmiString objects can be used interchangably.  That said, it is recommended that applications
		use the LmiPath exclusively to build file system paths.}

		{p:When mixing LmiPath and LmiString methods care must be taken not to invalidate the LmiPath
		when making calls to LmiString methods.  In particular, LmiPath methods insure that the path it holds is
		valid.  If an LmiPath object is used in an LmiString method the LmiPath may become invalid.  Calling
		LmiPathIsValid can determine if the LmiString method has in fact invalidated the path. Calling
		LmiPathMakeValid will make the path valid (but possibly incorrect) again.}
	}
 	{constant symbolic="no":
 		{name:lmiRootPrefix}
 		{type: const LmiString}
 		{description: The OS-specific file system root prefix.  For example on Unix-like system it is \"/\".  The root
 		  prefix is typically the same as the {code:lmiPathSeparator}.}}
  	{constant symbolic="no":
 		{name:lmiPathSeparator}
 		{type: const LmiString}
 		{description: The OS-specific file system path separator.  For example on Unix-like system its \"/\".  The path
 		  separator is typically the same as the {code:lmiRootPrefix}.}}
}
*/
typedef LmiString LmiPath;

/**
{function:
	{name: LmiPathConstruct}
	{parent: LmiPath}
	{description: Construct a path object from a string if the string is a valid path.}
	{prototype: LmiPath* LmiPathConstruct(LmiPath* x, const LmiString* path)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: path}
		{description: A string conforming to  OS-specific path syntax.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathConstruct(LmiPath* x, const LmiString* path);

/**
{function:
	{name: LmiPathConstructCopy}
	{parent: LmiPath}
	{description: Construct a path object from another path object.}
	{prototype: LmiPath* LmiPathConstructCopy(LmiPath* x, const LmiPath* y)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: y}
		{description: A path object to copy.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathConstructCopy(LmiPath* x, const LmiPath* y);

/**
{function:
	{name: LmiPathConstructFromComponents}
	{parent: LmiPath}
	{description: Construct a path object from a vector of components.}
	{prototype: LmiPath* LmiPathConstructFromComponents(LmiPath* x, const LmiStringVector* components)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: components}
		{description: The path components. There must be at least one component it the vector and each
 		  component must conform to the OS-specific syntax for path components.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathConstructFromComponents(LmiPath* x, const LmiStringVector* components);

/**
{function:
	{name: LmiPathDestruct}
	{parent: LmiPath}
	{description: Destruct a path object.}
	{prototype: void LmiPathDestruct(LmiPath* x)}
	{parameter:
		{name: x}
 		{description: The path object.}}
}
*/
void LmiPathDestruct(LmiPath* x);

/**
{function:
	{name: LmiPathAssign}
	{parent: LmiPath}
	{description: Assign one path object to another path object.}
	{prototype: LmiPath* LmiPathAssign(LmiPath* x, const LmiPath* y)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: y}
		{description: A path object to copy.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathAssign(LmiPath* x, const LmiPath* y);

/**
{function:
	{name: LmiPathAssignFromComponents}
	{parent: LmiPath}
	{description: Assign path object from a vector of path components.}
	{prototype: LmiPath* LmiPathAssignFromComponents(LmiPath* x, const LmiStringVector* components)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: components}
		{description: The path components. There must be at least one component it the vector and each
 		  component must conform to the OS-specific syntax for path components.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathAssignFromComponents(LmiPath* x, const LmiStringVector* components);

/**
{function:
	{name: LmiPathAppend}
	{parent: LmiPath}
	{description: Append a path component to a path object.}
	{prototype: LmiPath* LmiPathAppend(LmiPath* x, const LmiString* component)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: component}
		{description: A path component.  The path component must conform to the OS-specific component syntax.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathAppend(LmiPath* x, const LmiString* component);

/**
{function:
	{name: LmiPathAppendComponents}
	{parent: LmiPath}
	{description: Append a vector of path components to a path object.  Even the first component must not be a root prefix.}
	{prototype: LmiPath* LmiPathAppendComponents(LmiPath* x, const LmiStringVector* components)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: components}
		{description: The path components.  Each component must conform to the OS-specific syntax
 		  for path components.  The path component vector may be empty.}}
	{return: Returns a pointer to the path object on success, or NULL otherwise.}
}
*/
LmiPath* LmiPathAppendComponents(LmiPath* x, const LmiStringVector* components);

/**
{function:
	{name: LmiPathSwap}
	{parent: LmiPath}
	{description: Swap one path object with another path object.}
	{prototype: LmiBool LmiPathSwap(LmiPath* x, LmiPath* y)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: y}
		{description: A path object to swap with.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathSwap(LmiPath* x, LmiPath* y);

/* Don't publish yet:
Need to implement Unicode comparisons per each file system */
/*
{function:
	{name: LmiPathEqual}
	{parent: LmiPath}
	{description: Compare one path object with another path object for equality.  On Windows, the comparison is insensitive
	 to path separators \'/\' and \'\\\'.}
	{prototype: LmiBool LmiPathEqual(const LmiPath* x, const LmiPath* y)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: y}
		{description: A path object to compare with.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathEqual(const LmiPath* x, const LmiPath* y);

/**
{function:
	{name: LmiPathSplit}
	{parent: LmiPath}
	{description: Split a path object into a vector of path components .}
	{prototype: LmiBool LmiPathSplit(const LmiPath* x, LmiStringVector* components)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: components}
		{description: On successful return, the contents of this vector will be replaced by the path components.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathSplit(const LmiPath* x, LmiStringVector* components);

/**
{function:
	{name: LmiPathGetLastComponent}
	{parent: LmiPath}
	{description: Get the last component of a path object.}
	{prototype: LmiString* LmiPathGetLastComponent(const LmiPath* x, LmiString* component)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: component}
		{description: A string into which the last path component is copied. }}
	{return: Returns a pointer to the path component on success, or NULL otherwise.}
}
*/
LmiString* LmiPathGetLastComponent(const LmiPath* x, LmiString* component);

/**
{function:
	{name: LmiPathPushComponent}
	{parent: LmiPath}
	{description: Push a path component on to the end of a path object.}
	{prototype: LmiBool LmiPathPushComponent(LmiPath* x, const LmiString* component)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{parameter:
		{name: component}
		{description: A path component.  The path component must conform to the OS-specific component syntax.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathPushComponent(LmiPath* x, const LmiString* component);

/**
{function:
	{name: LmiPathPopComponent}
	{parent: LmiPath}
	{description: Pop the last component off a path object.}
	{prototype: LmiBool LmiPathPopComponent(LmiPath* x, )}
	{parameter:
		{name: x}
		{description: The path object.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise (including trying to pop the last component in the path).}
}
*/
LmiBool LmiPathPopComponent(LmiPath* x);

/**
{function:
	{name: LmiPathIsSelfDirectory}
	{parent: LmiPath}
	{description: Determines whether a path object is a \"self\" directory (typically \".\").}
	{prototype: LmiBool LmiPathIsSelfDirectory(const LmiPath* x)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{return: Returns LMI_TRUE if the path is a \"self\" directory, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathIsSelfDirectory(const LmiPath* x);

/**
{function:
	{name: LmiPathIsParentDirectory}
	{parent: LmiPath}
	{description: Determines whether a path object is a \"parent\" directory (typically \"..\").}
	{prototype: LmiBool LmiPathIsParentDirectory(const LmiPath* x)}
	{parameter:
		{name: x}
		{description: The path object.}}
	{return: Returns LMI_TRUE if the path is a \"parent\" directory, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathIsParentDirectory(const LmiPath* x);

/**
{function:
	{name: LmiPathIsValidComponent}
	{parent: LmiPath}
	{description: Determines whether a path component is valid.}
	{prototype: LmiBool LmiPathIsValidComponent(const LmiString* component)}
	{parameter:
		{name: component}
		{description: The path component.}}
	{return: Returns LMI_TRUE if the path component is valid, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathIsValidComponent(const LmiString* component);

/**
{function:
	{name: LmiPathIsValid}
	{parent: LmiPath}
	{description: Determines whether a path string is valid.}
	{prototype: LmiBool LmiPathIsValid(const LmiString* x)}
	{parameter:
		{name: x}
		{description: The path string.}}
	{return: Returns LMI_TRUE if the path string is valid, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathIsValid(const LmiString* path);

/**
{function:
	{name: LmiPathMakeValidComponent}
	{parent: LmiPath}
	{description: Modifies a path component to comply with OS-specific path component syntax.}
	{prototype: LmiBool LmiPathMakeValidComponent(LmiString* component)}
	{parameter:
		{name: component}
		{description: The path component.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise.}
}
*/

LmiBool LmiPathMakeValidComponent(LmiString* component);
/**
{function:
	{name: LmiPathMakeValid}
	{parent: LmiPath}
	{description: Modifies a path string to comply with OS-specific path component syntax.}
	{prototype: LmiBool LmiPathMakeValid(LmiString* path)}
	{parameter:
		{name: path}
		{description: The path string.}}
	{return: Returns LMI_TRUE on success, or LMI_FALSE otherwise.}
}
*/
LmiBool LmiPathMakeValid(LmiString* path);

extern const LmiString lmiRootPrefix;
extern const LmiString lmiPathSeparator;

#endif /* LMI_PATH_H */
