blob: 2b98c209f73750ff1f1cd270cb5c6d957ebae6ef [file] [log] [blame]
/*
*
* Copyright (c) 2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements functions to register and deregister
* support callbacks, particularly those for returning
* human-readable strings, for Weave profiles.
*
*/
#include <stddef.h>
#include <stdlib.h>
#include <Weave/Support/ProfileStringSupport.hpp>
namespace nl {
namespace Weave {
namespace Support {
/**
* Registry singly-linked list head pointer.
*/
static ProfileStringContext *sProfileStringContextHead;
/**
* @brief
* Find a profile string support context matching the specified
* context, based on the profile identifier associated with the
* context.
*
* This function finds a profile string support context matching the
* specified context, based on the profile identifier associated with
* the context.
*
* @param[in] inContext A read-only reference to the profile string
* support context to find.
*
* @return a read-only pointer to the profile string support context
* if found; otherwise, NULL.
*
*/
static ProfileStringContext *FindProfileStringContext(const ProfileStringContext &inContext)
{
ProfileStringContext *current;
current = sProfileStringContextHead;
while (current != NULL)
{
if (current->mStringInfo.mProfileId == inContext.mStringInfo.mProfileId)
{
break;
}
current = current->mNext;
}
return (current);
}
/**
* @brief
* Insert the specified profile string support context into the
* registry.
*
* This function inserts the specified profile string support context
* into the registry, if not already present, in sorted order, based
* on ascending profile identifier.
*
* @param[inout] inOutContext A reference to the profile string support
* context that will be inserted into the
* registry. While the context is present in
* the registry, the mNext field may be modified
* as other contexts are inserted or removed.
*
* @return true if the context was inserted; otherwise, false.
*
*/
static bool InsertProfileStringContext(ProfileStringContext &inOutContext)
{
ProfileStringContext *current;
ProfileStringContext *previous;
bool insert = true;
previous = NULL;
current = sProfileStringContextHead;
while (current != NULL)
{
if (current->mStringInfo.mProfileId == inOutContext.mStringInfo.mProfileId)
{
insert = false;
break;
}
else if (current->mStringInfo.mProfileId > inOutContext.mStringInfo.mProfileId)
{
insert = true;
break;
}
previous = current;
current = current->mNext;
}
if (insert)
{
if (previous != NULL)
{
// Insert a body or add a tail element
inOutContext.mNext = previous->mNext;
previous->mNext = &inOutContext;
}
else
{
// Add or replace the head
if (current != NULL)
{
// Replace the head element
inOutContext.mNext = sProfileStringContextHead;
}
sProfileStringContextHead = &inOutContext;
}
}
return (insert);
}
/**
* @brief
* Remove the specified profile string support context from the
* registry.
*
* This function removes the specified profile string support context
* from the registry, if present, based on the profile identifier.
*
* @param[inout] inOutContext A reference to the profile string support
* context that will be removed, if present.
* When the context is removed, the mNext
* field may be modified.
*
* @return true if the context was removed; otherwise, false.
*
*/
static bool RemoveProfileStringContext(ProfileStringContext &inOutContext)
{
ProfileStringContext *current;
ProfileStringContext *previous;
bool remove = false;
previous = NULL;
current = sProfileStringContextHead;
while (current != NULL)
{
if (current->mStringInfo.mProfileId == inOutContext.mStringInfo.mProfileId)
{
remove = true;
break;
}
previous = current;
current = current->mNext;
}
if (remove)
{
if (previous != NULL)
{
// Remove a body or tail element
previous->mNext = current->mNext;
}
else
{
// Remove the head element
sProfileStringContextHead = current->mNext;
}
current->mNext = NULL;
}
return (remove);
}
/**
* @brief
* Register the provided profile string support callbacks.
*
* This function registers and makes available the provided profile
* string support callbacks.
*
* @param[inout] inOutContext A reference to the profile string support
* context that will be registered and added
* to the registry. While the context is
* registered, the mNext field may be modified
* as other contexts are registered or
* unregistered.
*
* @retval #WEAVE_NO_ERROR On success.
*
* @retval #WEAVE_ERROR_PROFILE_STRING_CONTEXT_ALREADY_REGISTERED If the context is
* already registered.
*
* @sa FindStringProfileInfo
* @sa UnregisterProfielStringInfo
*
*/
NL_DLL_EXPORT WEAVE_ERROR RegisterProfileStringInfo(ProfileStringContext &inOutContext)
{
const bool status = InsertProfileStringContext(inOutContext);
return ((status)? WEAVE_NO_ERROR : WEAVE_ERROR_PROFILE_STRING_CONTEXT_ALREADY_REGISTERED);
}
/**
* @brief
* Unregister the provided profile string support callbacks.
*
* This function unregisters and makes unavailable the provided profile
* string support callbacks.
*
* @param[inout] inOutContext A reference to the profile string support
* context that will be unregistered, if
* registered, and removed from the registry.
* When the context is unregistered, the
* mNext field may be modified.
*
* @retval #WEAVE_NO_ERROR On success.
*
* @retval #WEAVE_ERROR_PROFILE_STRING_CONTEXT_NOT_REGISTERED If the context is not
* registered.
*
* @sa FindStringProfileInfo
* @sa RegisterProfielStringInfo
*
*/
NL_DLL_EXPORT WEAVE_ERROR UnregisterProfileStringInfo(ProfileStringContext &inOutContext)
{
const bool status = RemoveProfileStringContext(inOutContext);
return ((status) ? WEAVE_NO_ERROR : WEAVE_ERROR_PROFILE_STRING_CONTEXT_NOT_REGISTERED);
}
/**
* @brief
* Find, if registered, the profile string support callbacks associated
* with the specified profile identifier.
*
* @param[in] inProfileId The profile identifier to find string support
* callbacks for.
*
* @return a read-only pointer to the profile string support
* callbacks if found; otherwise, NULL.
*
* @sa RegisterProfielStringInfo
* @sa UnregisterProfielStringInfo
*
*/
NL_DLL_EXPORT const ProfileStringInfo *FindProfileStringInfo(uint32_t inProfileId)
{
const ProfileStringInfo info = { inProfileId, NULL, NULL, NULL };
const ProfileStringContext target = { NULL, info };
ProfileStringContext * context;
context = FindProfileStringContext(target);
return ((context != NULL) ? &context->mStringInfo : NULL);
}
}; // namespace Support
}; // namespace Weave
}; // namespace nl