# Ignore output dirs
/release
-/csdk/release
-/csdk/libcoap-4.1.1/release/
-/examples/release
+resource/release
+resource/csdk/release
+resource/csdk/libcoap-4.1.1/release/
+resource/examples/release
+resource/examples/debug
/debug
-csdk/debug/
-csdk/libcoap-4.1.1/debug/
-/examples/debug
-csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/debug
+resource/csdk/debug/
+resource/csdk/libcoap-4.1.1/debug/
+resource/csdk/libcoap-4.1.1/linux/
+resource/csdk/linux
+resource/csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/csdk/stack/samples/linux/SimpleClientServer/release/
+resource/csdk/connectivity/build/out/
+resource/oc_logger/bin/
+resource/oc_logger/lib/
+resource/oc_logger/samples/linux/release/
+resource/oc_logger/samples/linux/debug
+
+service/things-manager/build/linux/release
+service/things-manager/build/linux/debug
+service/things-manager/sdk/build/linux/
# Ignore any object files
*.o
*.obj
*.project
# Ignore dependencies folder, which should be generated
-/dependencies
+dependencies/
+
+#ignore Klocwork stuff
+.kwlp/
+.kwps/
+
+#ignore various swap files
+*.swp
buildScript_all: objdirs obj_build liboctbstack.a
-make_lcoap:
+make_lcoap:
$(MAKE) -C $(LCOAP_DIR) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)" "ARDUINOWIFI=$(ARDUINOWIFI)"
-objdirs:
+objdirs:
mkdir -p $(PLATFORM)
mkdir -p $(PLATFORM)/$(ARDUINO_SHIELD_TYPE)
mkdir -p $(OUT_DIR)
$(foreach source,$(SOURCES), $(CC) $(CFLAGS) $(source) -o $(patsubst %.c, %.o, $(patsubst %, $(OBJ_DIR)/%, $(notdir $(source))));)
liboctbstack.a: obj_build
- @echo "Building $@"
+ @echo "Building $@"
# Unpackage libcoap.a to $(OBJ_DIR)/$(BUILD). The output objects from OCStack and OCCoap are already at this location
@cd $(OBJ_DIR) && $(AR) -x $(PLATFORM_SPECIFIC_BACKOUT)$(LCOAP_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/libcoap.a
# Repackage all the objects at this location into a single archive. This is OCStack, OCCoap, and LibCoap (LibCoap contains OCRandom, OCLogger, and OCSocket.).
$(AR) -r $(OUT_DIR)/$@ $(OBJ_DIR)/*.o
-
+
ifeq ($(PLATFORM),linux)
ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),)
$(info "Building liboctbstack with DTLS support")
{
// silence warnings
(void) ctx;
- OCServerProtocolRequest protocolRequest;
- memset(&protocolRequest, 0, sizeof(OCServerProtocolRequest));
+ OCServerProtocolRequest protocolRequest = {(OCMethod)0};
coap_block_t rcvdBlock1;
coap_block_t rcvdBlock2;
memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
const coap_queue_t * rcvdResponse) {
OCResponse * response = NULL;
OCCoAPToken rcvdToken;
- OCClientResponse clientResponse;
- memset(&clientResponse, 0, sizeof(OCClientResponse));
+ OCClientResponse clientResponse = {0};
ClientCB * cbNode = NULL;
unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
isPresenceNotification = 1;
OC_LOG(INFO, TAG, PCF("Received a presence notification"));
- tok = strtok((char *)bufRes, "[:]");
- tok = strtok(NULL, "[:]");
+ tok = strtok((char *)bufRes, "[:]}");
+ bufRes[strlen((char *)bufRes)] = ':';
+ tok = strtok(NULL, "[:]}");
+ bufRes[strlen((char *)bufRes)] = ':';
VERIFY_NON_NULL(tok);
sequenceNumber = (uint32_t )atol(tok);
OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
- tok = strtok(NULL, "[:]");
+ tok = strtok(NULL, "[:]}");
VERIFY_NON_NULL(tok);
maxAge = (uint32_t )atol(tok);
OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
- tok = strtok(NULL, "[:]");
- bufRes[strlen((char *)bufRes)] = ':';
+ tok = strtok(NULL, "[:]}");
if(tok) {
+ bufRes[strlen((char *)bufRes)] = ':';
resourceTypeName = (char *)OCMalloc(strlen(tok));
if(!resourceTypeName)
{
goto exit;
}
strcpy(resourceTypeName, tok);
- bufRes[strlen((char *)bufRes)] = ':';
OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
resourceTypeName);
}
+ bufRes[strlen((char *)bufRes)] = ']';
}
#endif
cbNode = GetClientCB(&rcvdToken, NULL, NULL);
#ifdef WITH_PRESENCE
- // Check if the application subcribed for presence
+ // Check if the application subscribed for presence
if(!cbNode)
{
// get the address of the remote
sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
cbNode = GetClientCB(NULL, NULL, fullUri);
isMulticastPresence = 1;
+ isPresenceNotification = 0;
}
#endif
cbNode->sequenceNumber = clientResponse.sequenceNumber;;
}
+ // Ensure that a filter is actually applied.
if(resourceTypeName && response->cbNode->filterResourceType)
{
- if(strcmp(resourceTypeName,
- (const char *)response->cbNode->filterResourceType)!=0)
+ if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
{
- //Ignore presence callback if resource type does not match filter.
goto exit;
}
}
remotePortNu);
mcNode = GetMCPresenceNode(senderUri);
- if(mcNode != NULL)
+ if(maxAge == 0)
+ {
+ OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+ response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+ if(cbNode->presence)
+ {
+ OCFree(cbNode->presence->timeOut);
+ OCFree(cbNode->presence);
+ cbNode->presence = NULL;
+ }
+ }
+ else if(mcNode != NULL)
{
if(mcNode->nonce == clientResponse.sequenceNumber)
{
}
}
+ // Ensure that a filter is actually applied.
if(resourceTypeName && response->cbNode->filterResourceType)
{
- if(strcmp(resourceTypeName,
- (const char *)response->cbNode->filterResourceType)!=0)
+ if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
{
- //Ignore presence callback if resource type does not match filter.
goto exit;
}
}
-
}
#endif
}
VERIFY_SUCCESS(result, OC_STACK_OK);
}
exit:
+ OCFree(resourceTypeName);
OCFree(response);
}
* Allocates a block of size bytes, returning a pointer to the beginning of
* the allocated block.
*
- * NOTE: This function is intended to be used internally by the TB Stack.
- * It is not intended to be used by applications.
- *
* @param size - Size of the memory block in bytes, where size > 0
*
* @return
void *OCMalloc(size_t size);
/**
- * Deallocate a block of memory previously allocated by a call to OCMalloc
+ * Allocates a block of memory for an array of num elements, each of them
+ * size bytes long and initializes all its bits to zero.
+ *
+ * @param num - The number of elements
+ * @param size - Size of the element type in bytes, where size > 0
*
- * NOTE: This function is intended to be used internally by the TB Stack.
- * It is not intended to be used by applications.
+ * @return
+ * on success, a pointer to the allocated memory block
+ * on failure, a null pointer is returned
+ */
+void *OCCalloc(size_t num, size_t size);
+
+/**
+ * Deallocate a block of memory previously allocated by a call to OCMalloc
*
* @param ptr - Pointer to block of memory previously allocated by OCMalloc.
* If ptr is a null pointer, the function does nothing.
void *OCMalloc(size_t size)
{
-#ifdef ENABLE_MALLOC_DEBUG
- void *ptr = 0;
-
if (0 == size)
{
return NULL;
}
+#ifdef ENABLE_MALLOC_DEBUG
+ void *ptr = 0;
+
ptr = malloc(size);
OC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u", ptr, size);
return ptr;
#else
- if (0 == size)
+ return malloc(size);
+#endif
+}
+
+void *OCCalloc(size_t num, size_t size)
+{
+ if(0 == size || 0 == num)
{
return NULL;
}
- return malloc(size);
+
+#ifdef ENABLE_MALLOC_DEBUG
+ void *ptr = 0;
+
+ ptr = calloc(num, size);
+ OC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size);
+ return ptr;
+#else
+ return calloc(num, size);
#endif
}
INC_DIRS += -I$(GTEST_DIR)/include
CC_FLAGS.debug := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
- -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+ -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
- -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD)
-
-LDLIBS += -loctbstack -lgtest -lgtest_main -lpthread
-CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
+ -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD)
+
+LDLIBS += -loctbstack -lpthread
+CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) $(GTEST_DIR)/lib/.libs/libgtest.a \
+ $(GTEST_DIR)/lib/.libs/libgtest_main.a
SOURCES := unittest.cpp
PROGRAMS := unittest
-all: prep_dirs $(OBJECTS) $(PROGRAMS)
+all: prep_dirs $(OBJECTS) $(PROGRAMS)
prep_dirs:
-mkdir -p $(OUT_DIR)
$(OBJ_DIR)/%.o: %.cpp
$(CC) -c $(CPPFLAGS) $< -o $@
-unittest: $(OBJ_DIR)/unittest.o
+unittest: $(OBJ_DIR)/unittest.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
.PHONY: clean
EXPECT_TRUE(NULL == pBuffer);
OCFree(pBuffer);
}
+
+TEST(OCCalloc, CallocPass1)
+{
+ // Try to allocate a small buffer
+ pBuffer = (uint8_t *)OCCalloc(1, 1);
+ EXPECT_TRUE(pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass2)
+{
+ // Try to allocate a small buffer
+ pBuffer = (uint8_t *)OCCalloc(1, 128);
+ EXPECT_TRUE(pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass3)
+{
+ // Try to allocate a buffer for an array
+ pBuffer = (uint8_t *)OCCalloc(5, 128);
+ EXPECT_TRUE(pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail1)
+{
+ // Try to allocate a buffer of size 0
+ pBuffer = (uint8_t *)OCCalloc(1, 0);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail2)
+{
+ // Try to allocate a buffer with num of 0
+ pBuffer = (uint8_t *)OCCalloc(0, 5);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail3)
+{
+ // Try to allocate a buffer with size and num 0
+ pBuffer = (uint8_t *)OCCalloc(0, 0);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail4)
+{
+ // Try to allocate a ridiculous amount of RAM
+ pBuffer = (uint8_t *)OCCalloc(1, (size_t)0x7FFFFFFFFFFFFFFF);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
uint8_t *addrv4, uint32_t addrLen);
+//-- OCDevAddrToString ----------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to convert the OCDevAddr to string format
+ *
+ * @param[in] addr
+ * OCDevAddr address.
+ * @param[out] stringAddress the target string where the address
+ * is to be stored. Memory for this parameter is
+ * allocated by the caller.
+ *
+ * Note: The length of stringAddress may not exceed DEV_ADDR_SIZE_MAX
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCDevAddrToString(OCDevAddr *addr, char *stringAddress);
+
+
//-- OCDevAddrToIPv4Addr -------------------------------------------------
/** @ingroup ocsocket
*
}
// bind to multicast port
- struct sockaddr_in sa;
+ struct sockaddr_in sa = {0};
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)(ipmcastaddr->addr);
- memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = sin->sin_addr.s_addr;
sa.sin_port = sin->sin_port;
}
// add membership to receiving socket
- struct ip_mreq mreq;
- memset(&mreq, 0, sizeof(struct ip_mreq));
+ struct ip_mreq mreq = {0};
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
return (close(sockfd));
}
+//convert OCDevAddr to String
+int32_t OCDevAddrToString(OCDevAddr* addr, char* stringAddress)
+{
+ uint8_t a;
+ uint8_t b;
+ uint8_t c;
+ uint8_t d;
+
+ if(OCDevAddrToIPv4Addr(addr, &a, &b, &c, &d) == 0)
+ {
+ if (!stringAddress)
+ {
+ return ERR_INVALID_INPUT;
+ }
+
+ sprintf(stringAddress, "%u.%u.%u.%u",
+ a, b, c, d);
+ return ERR_SUCCESS;
+ }
+ else
+ {
+ return ERR_INVALID_INPUT;
+ }
+}
/// Retrieve the IPv4 address embedded inside OCDev address data structure
int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
int32_t sfd;
char loopch=0;
int set_option_on = 1;
- struct sockaddr_in mcastsock, peer;
+ struct sockaddr_in mcastsock = {0}, peer;
uint8_t recvbuf[MAX_BUF];
uint32_t len, bufLen, fromlen;
}
//Initialize the group sockaddr structure with a
- memset((char *) &mcastsock, 0, sizeof(mcastsock));
mcastsock.sin_family = AF_INET;
mcastsock.sin_addr.s_addr = inet_addr(argv[2]);
mcastsock.sin_port = htons(atoi(argv[3]));
return -1;
}
- struct ip_mreq mreq;
- memset(&mreq, 0, sizeof(struct ip_mreq));
+ struct ip_mreq mreq = {0};
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_multiaddr.s_addr = mcastsock.sin_addr.s_addr;
if ((setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
#include <ocstack.h>
#include <occoaptoken.h>
+#include <ocresource.h>
typedef struct OCPresence {
// This is the TTL associated with presence
// Struct to hold TTL info for presence
#ifdef WITH_PRESENCE
OCPresence * presence;
- unsigned char * filterResourceType;
+ OCResourceType * filterResourceType;
#endif
// next node in this list
struct ClientCB *next;
* @param[in] requestUri
* the resource uri of the request.
* @param[in] resourceType
- * the resourceType associated with this request.
+ * the resourceType associated with a presence request.
*
* @brief If the handle you're looking for does not exist, the stack will reply with a RST message.
*
*/
//------------------------------------------------------------------------
OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
- OCCoAPToken * token, OCDoHandle handle, OCMethod method,
+ OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
unsigned char * requestUri, unsigned char * resourceType);
//-- DeleteClientCB -----------------------------------------------------------
//------------------------------------------------------------------------
ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
+
+/**
+ * Inserts a new resource type filter into this clientCB node.
+ *
+ * @param cbNode - the node to add the new resourceType filter to
+ * @param resourceTypeName - the value to create the new resourceType filter from
+ *
+ * @return
+ * OC_STACK_OK on success
+ * OC_STACK_ERROR with invalid parameters
+ * OC_STACK_NO_MEMORY when out of memory
+ */
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+
//-- DeleteClientCBList --------------------------------------------------
/** @ingroup ocstack
*
#define OC_COLLECTION_H
#include "ocstack.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
uint8_t GetNumOfResourcesInCollection (OCResource *resource);
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#ifndef OC_RESOURCE_H
-#define OC_RESOURCE_H
-
-#include "ocstack.h"
-#include "ocstackinternal.h"
-#include "ocserverrequest.h"
-
-#define OC_RSRVD_OC "oc"
-#define OC_RSRVD_PAYLOAD "payload"
-#define OC_RSRVD_HREF "href"
-#define OC_RSRVD_RESOURCE_TYPE "rt"
-#define OC_RSRVD_INTERFACE "if"
-#define OC_RSRVD_INTERFACE_DEFAULT "oc.mi.def"
-#define OC_RSRVD_INTERFACE_LL "oc.mi.ll"
-#define OC_RSRVD_INTERFACE_BATCH "oc.mi.b"
-#define OC_RSRVD_OBSERVABLE "obs"
-#define OC_RSRVD_SECURE "sec"
-#define OC_RSRVD_HOSTING_PORT "port"
-
-#define OC_JSON_PREFIX "{\"oc\":["
-#define OC_JSON_PREFIX_LEN (sizeof(OC_JSON_PREFIX) - 1)
-#define OC_JSON_SUFFIX "]}"
-#define OC_JSON_SUFFIX_LEN (sizeof(OC_JSON_SUFFIX) - 1)
-#define OC_JSON_SEPARATOR ','
-
-#define OC_RESOURCE_OBSERVABLE 1
-#define OC_RESOURCE_SECURE 1
+#ifndef OCRESOURCE_H_
+#define OCRESOURCE_H_
-typedef enum {
- STACK_RES_DISCOVERY_NOFILTER = 0,
- STACK_RES_DISCOVERY_IF_FILTER,
- STACK_RES_DISCOVERY_RT_FILTER
-} StackQueryTypes;
+#define OC_OBSERVER_NOT_INTERESTED (0)
+#define OC_OBSERVER_STILL_INTERESTED (1)
+#define OC_OBSERVER_FAILED_COMM (2)
+
+//-----------------------------------------------------------------------------
+// Virtual Resource Presence Attributes
+//-----------------------------------------------------------------------------
+#ifdef WITH_PRESENCE
+typedef struct PRESENCERESOURCE{
+ OCResourceHandle handle;
+ uint32_t presenceTTL;
+} PresenceResource;
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct rsrc_t;
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+// IF here stands for Interface
typedef enum {
- OC_RESOURCE_VIRTUAL = 0,
- OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
- OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
- OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
- OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
- OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
- OC_RESOURCE_NOT_SPECIFIED
-} ResourceHandling;
+ STACK_IF_DEFAULT = 0,
+ STACK_IF_LL,
+ STACK_IF_BATCH,
+ STACK_IF_INVALID
+} OCStackIfTypes;
+
+typedef struct resourcetype_t {
+ struct resourcetype_t *next; // linked list; for multiple types on resource
+
+ // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
+ // namespace and the final segment is the type; type and sub-types can be separate with
+ // ‘-‘ (dash) usually only two segments would be defined. Either way this string is meant to be
+ // human friendly and is used opaquely and not parsed by code. This name is used in the “rt=”
+ // parameter of a resource description when resources are introspected and is also use in the
+ // <base URI>/types list of available types.
+ char *resourcetypename;
+} OCResourceType;
+
+typedef struct attr_t {
+ struct attr_t *next; // Points to next resource in list
+
+ // The name of the attribute; used to look up the attribute in list;
+ // for a given attribute SHOULD not be changed once assigned
+ const char *attrName;
+ char *attrValue; // value of the attribute as string
+} OCAttribute;
-OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * request);
+typedef struct resourceinterface_t {
+ struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-const char * GetVirtualResourceUri( OCVirtualResources resource);
-OCResource *FindResourceByUri(const char* resourceUri);
-uint8_t IsVirtualResource(const char* resourceUri);
+ // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is a
+ // namespace and the final segment is the interface; usually only two segments would be
+ // defined. Either way this string is opaque and not parsed by segment
+ char *name ;
-OCStackResult DetermineResourceHandling (OCServerRequest *request,
- ResourceHandling *handling,
- OCResource **resource);
+ // Supported content types to serialize request and response on this interface
+ // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
+#if 0
+ char *inputContentType ;
+ char *outputContentType ;
+#endif
+ /*** Future placeholder for access control and policy ***/
+} OCResourceInterface;
-OCStackResult
-ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+typedef struct rsrc_t {
+ struct rsrc_t *next; // Points to next resource in list
+ // Relative path on the device; will be combined with base url to create fully qualified path
+ char *host;
+ char *uri;
+ OCResourceType *rsrcType; // Resource type(s); linked list
+ OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
+ OCAttribute *rsrcAttributes; // Resource interface(s); linked list
+ // Array of pointers to resources; can be used to represent a container of resources
+ // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
+ struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
+ //struct rsrc_t *rsrcResources;
+ // Pointer to function that handles the entity bound to the resource.
+ // This handler has to be explicitly defined by the programmer
+ OCEntityHandler entityHandler;
+ // Properties on the resource – defines meta information on the resource
+ OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
+ // Pointer to an opaque object where app/user specific data can be placed with the resource;
+ // this could be information for the entity handler between invocations
+ void *context;
+ // NOTE: Methods supported by this resource should be based on the interface targeted
+ // i.e. look into the interface structure based on the query request Can be removed here;
+ // place holder for the note above
+ /* method_t methods; */
+ // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
+ uint32_t sequenceNum;
+} OCResource;
-OCStackResult
-BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
- char *filterValue, char * out, uint16_t *remaining);
-OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
-#endif //OC_RESOURCE_H
+#endif /* OCRESOURCE_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_RESOURCEHANDLER_H
+#define OC_RESOURCEHANDLER_H
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+
+#define OC_RSRVD_OC "oc"
+#define OC_RSRVD_PAYLOAD "payload"
+#define OC_RSRVD_HREF "href"
+#define OC_RSRVD_RESOURCE_TYPE "rt"
+#define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence"
+#define OC_RSRVD_INTERFACE "if"
+#define OC_RSRVD_INTERFACE_DEFAULT "oc.mi.def"
+#define OC_RSRVD_INTERFACE_LL "oc.mi.ll"
+#define OC_RSRVD_INTERFACE_BATCH "oc.mi.b"
+#define OC_RSRVD_OBSERVABLE "obs"
+#define OC_RSRVD_SECURE "sec"
+#define OC_RSRVD_HOSTING_PORT "port"
+
+#define OC_JSON_PREFIX "{\"oc\":["
+#define OC_JSON_PREFIX_LEN (sizeof(OC_JSON_PREFIX) - 1)
+#define OC_JSON_SUFFIX "]}"
+#define OC_JSON_SUFFIX_LEN (sizeof(OC_JSON_SUFFIX) - 1)
+#define OC_JSON_SEPARATOR ','
+
+#define OC_RESOURCE_OBSERVABLE 1
+#define OC_RESOURCE_SECURE 1
+
+typedef enum {
+ STACK_RES_DISCOVERY_NOFILTER = 0,
+ STACK_RES_DISCOVERY_IF_FILTER,
+ STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+typedef enum {
+ OC_RESOURCE_VIRTUAL = 0,
+ OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
+ OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
+ OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
+ OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+ OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
+ OC_RESOURCE_NOT_SPECIFIED
+} ResourceHandling;
+
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest * request);
+
+const char * GetVirtualResourceUri( OCVirtualResources resource);
+OCResource *FindResourceByUri(const char* resourceUri);
+uint8_t IsVirtualResource(const char* resourceUri);
+
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
+ ResourceHandling *handling,
+ OCResource **resource);
+
+OCStackResult
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+
+OCStackResult
+BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
+ char *filterValue, char * out, uint16_t *remaining);
+
+OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
+
+#endif //OC_RESOURCEHANDLER_H
#define OC_COAP_SCHEME "coap://"
#define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5
-#define OC_OBSERVER_NOT_INTERESTED (0)
-#define OC_OBSERVER_STILL_INTERESTED (1)
-#define OC_OBSERVER_FAILED_COMM (2)
-
-//-----------------------------------------------------------------------------
-// Virtual Resource Presence Attributes
-//-----------------------------------------------------------------------------
-#ifdef WITH_PRESENCE
-typedef struct PRESENCERESOURCE{
- OCResourceHandle handle;
- uint32_t presenceTTL;
-} PresenceResource;
-#endif
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-struct rsrc_t;
-
-//-----------------------------------------------------------------------------
-// Typedefs
-//-----------------------------------------------------------------------------
-
-// IF here stands for Interface
-typedef enum {
- STACK_IF_DEFAULT = 0,
- STACK_IF_LL,
- STACK_IF_BATCH,
- STACK_IF_INVALID
-} OCStackIfTypes;
-
-typedef struct resourcetype_t {
- struct resourcetype_t *next; // linked list; for multiple types on resource
-
- // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
- // namespace and the final segment is the type; type and sub-types can be separate with ‘-‘ (dash)
- // usually only two segments would be defined. Either way this string is meant to be human friendly
- // and is used opaquely and not parsed by code
- // This name is used in the “rt=” parameter of a resource description when resources are introspected
- // and is also use in the <base URI>/types list of available types
- char *resourcetypename;
-} OCResourceType;
-
-typedef struct attr_t {
- struct attr_t *next; // Points to next resource in list
-
- // The name of the attribute; used to look up the attribute in list;
- // for a given attribute SHOULD not be changed once assigned
- const char *attrName;
- char *attrValue; // value of the attribute as string
-} OCAttribute;
-
-typedef struct resourceinterface_t {
- struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-
- // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is
- // a namespace and the final segment is the interface; usually only two segments would be defined.
- // Either way this string is opaque and not parsed by segment
- char *name ;
-
- // Supported content types to serialize request and response on this interface
- // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
-#if 0
- char *inputContentType ;
- char *outputContentType ;
-#endif
- /*** Future placeholder for access control and policy ***/
-} OCResourceInterface;
-
-typedef struct rsrc_t {
- struct rsrc_t *next; // Points to next resource in list
- // Relative path on the device; will be combined with base url to create fully qualified path
- char *host;
- char *uri;
- OCResourceType *rsrcType; // Resource type(s); linked list
- OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
- OCAttribute *rsrcAttributes; // Resource interface(s); linked list
- // Array of pointers to resources; can be used to represent a container of resources
- // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
- struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
- //struct rsrc_t *rsrcResources;
- // Pointer to function that handles the entity bound to the resource.
- // This handler has to be explicitly defined by the programmer
- OCEntityHandler entityHandler;
- // Properties on the resource – defines meta information on the resource
- OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
- // Pointer to an opaque object where app/user specific data can be placed with the resource;
- // this could be information for the entity handler between invocations
- void *context;
- // NOTE: Methods supported by this resource should be based on the interface targeted
- // i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
- /* method_t methods; */
- // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
- uint32_t sequenceNum;
-} OCResource;
-
typedef struct {
// Observe option field
uint32_t option;
// following structure will be created in occoap and passed up the stack on the server side
typedef struct {
+ // Observe option field
+ uint32_t observationOption;
// the REST method retrieved from received request PDU
OCMethod method;
// resourceUrl will be filled in occoap using the path options in received request PDU
unsigned char reqJSONPayload[MAX_REQUEST_LENGTH];
// qos is indicating if the request is CON or NON
OCQualityOfService qos;
- // Observe option field
- uint32_t observationOption;
// An array of the received vendor specific header options
uint8_t numRcvdVendorSpecificHeaderOptions;
OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
typedef struct
{
- // qos is indicating if the request is CON or NON
- OCQualityOfService qos;
// Observe option field
uint32_t observationOption;
+ // qos is indicating if the request is CON or NON
+ OCQualityOfService qos;
// Allow the entity handler to pass a result with the response
OCStackResult result;
// IP address & port of client registered for observe
OCStackResult BindResourceTypeToResource(OCResource* resource,
const char *resourceTypeName);
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName);
#ifdef WITH_PRESENCE
//TODO: should the following function be public?
* Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
*/
typedef struct {
- // the is the result of our stack, OCStackResult should contain coap/other error codes;
- OCStackResult result;
// Address of remote server
OCDevAddr * addr;
+ // the is the result of our stack, OCStackResult should contain coap/other error codes;
+ OCStackResult result;
// If associated with observe, this will represent the sequence of notifications from server.
uint32_t sequenceNumber;
// resJSONPayload is retrieved from the payload of the received request PDU
OCStackResult OCProcess();
/**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource (specified by that Resource's respective
+ * URI).
*
- * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of
+ * calling this API.
* @param method - @ref OCMethod to perform on the resource
* @param requiredUri - URI of the resource to interact with
* @param referenceUri - URI of the reference resource
* header options to be sent with the request
* @param numOptions - Number of header options to be included
*
+ * Note: Presence subscription amendments (ie. adding additional resource type filters by calling
+ * this API again) require the use of the same base URI as the original request to successfully
+ * amend the presence filters.
+ *
* @return
* OC_STACK_OK - no errors
* OC_STACK_INVALID_CALLBACK - invalid callback function pointer
PROGMEM const char TAG[] = "ArduinoServer";
-int gLEDUnderObservation = 0;
-void createLEDResource();
-typedef struct LEDRESOURCE{
+int gLightUnderObservation = 0;
+void createLightResource();
+
+/* Structure to represent a Light resource */
+typedef struct LIGHTRESOURCE{
OCResourceHandle handle;
bool state;
int power;
-} LEDResource;
+} LightResource;
-static LEDResource LED;
+static LightResource Light;
-static char responsePayloadGet[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
-static char responsePayloadPut[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"power\":0}}";
+static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"off\",\"power\":0}}";
/// This is the port which Arduino Server will use for all unicast communication with it's peers
static uint16_t OC_WELL_KNOWN_PORT = 5683;
// http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
void PrintArduinoMemoryStats()
{
-#ifdef ARDUINO_AVR_MEGA2560
+ #ifdef ARDUINO_AVR_MEGA2560
//This var is declared in avr-libc/stdlib/malloc.c
//It keeps the largest address not allocated for heap
extern char *__brkval;
int tmp;
OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
- ((unsigned int)&tmp - (unsigned int)__brkval));
-#endif
+ ((unsigned int)&tmp - (unsigned int)__brkval));
+ #endif
}
// This is the entity handler for the registered resource.
{
ehRet = OC_EH_ERROR;
}
- }
+ }
if (ehRet == OC_EH_OK)
{
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
- gLEDUnderObservation = 1;
+ gLightUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
{
return ehRet;
}
-
// This method is used to display 'Observe' functionality of OC Stack.
static uint8_t modCounter = 0;
-void *ChangeLEDRepresentation (void *param)
+void *ChangeLightRepresentation (void *param)
{
(void)param;
OCStackResult result = OC_STACK_ERROR;
modCounter += 1;
if(modCounter % 10 == 0) // Matching the timing that the Linux Sample Server App uses for the same functionality.
{
- LED.power += 5;
- if (gLEDUnderObservation)
+ Light.power += 5;
+ if (gLightUnderObservation)
{
- OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power);
- result = OCNotifyAllObservers (LED.handle, OC_NA_QOS);
+ OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
+ result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
if (OC_STACK_NO_OBSERVERS == result)
{
- gLEDUnderObservation = 0;
+ gLightUnderObservation = 0;
}
}
}
return NULL;
}
-
-
//The setup function is called once at startup of the sketch
void setup()
{
// Add your initialization code here
-
// Note : This will initialize Serial port on Arduino at 115200 bauds
OC_LOG_INIT();
-
OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
uint16_t port = OC_WELL_KNOWN_PORT;
return;
}
- // Declare and create the example resource: LED
- createLEDResource();
-
+ // Declare and create the example resource: Light
+ createLightResource();
}
// The loop function is called in an endless loop
OC_LOG(ERROR, TAG, PCF("OCStack process error"));
return;
}
- ChangeLEDRepresentation(NULL);
+ ChangeLightRepresentation(NULL);
}
-void createLEDResource()
+void createLightResource()
{
- LED.state = false;
- OCStackResult res = OCCreateResource(&LED.handle,
- "core.led",
+ Light.state = false;
+ OCStackResult res = OCCreateResource(&Light.handle,
+ "core.light",
"oc.mi.def",
- "/a/led",
+ "/a/light",
OCEntityHandlerCb,
OC_DISCOVERABLE|OC_OBSERVABLE);
- OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+ OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
}
const char *getResult(OCStackResult result) {
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+ if(clientResponse == NULL)
+ {
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
}
- if(clientResponse)
- {
- OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
- }
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
+
if(clientResponse->rcvdVendorSpecificHeaderOptions &&
clientResponse->numRcvdVendorSpecificHeaderOptions)
{
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
{
+ if(clientResponse == NULL)
+ {
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
}
- if(clientResponse)
- {
- OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
- clientResponse->resJSONPayload);
- }
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+ clientResponse->resJSONPayload);
+
if(clientResponse->rcvdVendorSpecificHeaderOptions &&
clientResponse->numRcvdVendorSpecificHeaderOptions)
{
}
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
- if(clientResponse) {}
+ if(clientResponse == NULL)
+ {
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
{
+ if(clientResponse == NULL)
+ {
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
}
- if(clientResponse)
- {
- OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
- clientResponse->resJSONPayload);
- }
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+ clientResponse->resJSONPayload);
+
if(clientResponse->rcvdVendorSpecificHeaderOptions &&
clientResponse->numRcvdVendorSpecificHeaderOptions)
{
#include "cJSON.h"
#include "ocserver.h"
+//string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
+// 9 + 9 + 1 = 19
+const int URI_MAXSIZE = 19;
static int gObserveNotifyType = 3;
if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
{
// Create new Light instance
- char newLightUri[15] = "/a/light/";
- sprintf (newLightUri + strlen(newLightUri), "%d", gCurrLightInstance);
+ char newLightUri[URI_MAXSIZE];
+ snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
+
json = cJSON_CreateObject();
cJSON_AddStringToObject(json,"href",gResourceUri);
cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
+ if(ehRequest == NULL)
+ {
+ OC_LOG(INFO, TAG, "The ehRequest is NULL");
+ return OC_EH_ERROR;
+ }
OCEntityHandlerResult ehResult = OC_EH_OK;
OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
OCObservationId obsNotify[numNotifies];
- while (1)
+ while (!gQuitFlag)
{
sleep(10);
Light.power += 5;
#include "cJSON.h"
#include "ocserverbasicops.h"
+//string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
+// 7 + 9 + 1 = 17
+const int URI_MAXSIZE = 17;
+
volatile sig_atomic_t gQuitFlag = 0;
static LEDResource LED;
if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
{
// Create new LED instance
- char newLedUri[15] = "/a/led/";
- sprintf (newLedUri + strlen(newLedUri), "%d", gCurrLedInstance);
+ char newLedUri[URI_MAXSIZE ];
+ snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
json = cJSON_CreateObject();
(void)param;
OCStackResult result = OC_STACK_ERROR;
- while (1)
+ while (!gQuitFlag)
{
sleep(10);
light.power += 5;
if (gLightUnderObservation)
{
- OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", light.power);
+ OC_LOG_V(INFO, TAG,
+ " =====> Notifying stack of new power level %d\n", light.power);
result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
if (OC_STACK_NO_OBSERVERS == result)
{
res = OCBindResource(room, fan);
OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
}
-
-
OCMulticastNode * mcPresenceNodes = NULL;
OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
- OCCoAPToken * token, OCDoHandle handle, OCMethod method,
- unsigned char * requestUri, unsigned char * resourceType) {
- ClientCB *cbNode;
- cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
- if (cbNode) {
- cbNode->callBack = cbData->cb;
- cbNode->context = cbData->context;
- cbNode->deleteCallback = cbData->cd;
- memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
- cbNode->handle = handle;
- cbNode->method = method;
- cbNode->sequenceNumber = 0;
- #ifdef WITH_PRESENCE
- cbNode->presence = NULL;
- cbNode->filterResourceType = resourceType;
- #endif
- cbNode->requestUri = requestUri;
- LL_APPEND(cbList, cbNode);
+ OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
+ unsigned char * requestUri, unsigned char * resourceTypeName) {
+
+ ClientCB *cbNode = NULL;
+
+ #ifdef WITH_PRESENCE
+ if(method == OC_REST_PRESENCE)
+ { // Retrieve the presence callback structure for this specific requestUri.
+ cbNode = GetClientCB(NULL, NULL, requestUri);
+ }
+ #endif // WITH_PRESENCE
+
+ if(!cbNode)// If it does not already exist, create new node.
+ {
+ cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
+ if(!cbNode)
+ {
+ *clientCB = NULL;
+ goto exit;
+ }
+ else
+ {
+ cbNode->callBack = cbData->cb;
+ cbNode->context = cbData->context;
+ cbNode->deleteCallback = cbData->cd;
+ memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
+ cbNode->handle = *handle;
+ cbNode->method = method;
+ cbNode->sequenceNumber = 0;
+ #ifdef WITH_PRESENCE
+ cbNode->presence = NULL;
+ cbNode->filterResourceType = NULL;
+ #endif // WITH_PRESENCE
+ cbNode->requestUri = requestUri;
+ LL_APPEND(cbList, cbNode);
+ *clientCB = cbNode;
+ }
+ }
+ else
+ {
+ // Ensure that the handle the SDK hands back up to the application layer for the
+ // OCDoResource call matches the found ClientCB Node.
*clientCB = cbNode;
- return OC_STACK_OK;
+ OCFree(requestUri);
+ OCFree(*handle);
+ *handle = cbNode->handle;
}
- *clientCB = NULL;
- return OC_STACK_NO_MEMORY;
+
+ #ifdef WITH_PRESENCE
+ if(method == OC_REST_PRESENCE && resourceTypeName)
+ { // Amend the found or created node by adding a new resourceType to it.
+ return InsertResourceTypeFilter(cbNode, (const char *)resourceTypeName);
+ }
+ #endif
+
+ return OC_STACK_OK;
+
+ exit:
+ return OC_STACK_NO_MEMORY;
}
void DeleteClientCB(ClientCB * cbNode) {
if(cbNode->presence) {
OCFree(cbNode->presence->timeOut);
OCFree(cbNode->presence);
- OCFree(cbNode->filterResourceType);
}
- #endif
+ if(cbNode->method == OC_REST_PRESENCE)
+ {
+ OCResourceType * pointer = cbNode->filterResourceType;
+ OCResourceType * next = NULL;
+ while(pointer)
+ {
+ next = pointer->next;
+ OCFree(pointer->resourcetypename);
+ OCFree(pointer);
+ pointer = next;
+ }
+ }
+ #endif // WITH_PRESENCE
OCFree(cbNode);
cbNode = NULL;
}
return NULL;
}
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
+{
+ OCResourceType * newResourceType = NULL;
+ if(cbNode && resourceTypeName)
+ {
+ // Form a new resourceType member.
+ newResourceType = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+ if(!newResourceType)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+
+ newResourceType->next = NULL;
+ newResourceType->resourcetypename = (char *) resourceTypeName;
+
+ LL_APPEND(cbNode->filterResourceType, newResourceType);
+ return OC_STACK_OK;
+ }
+ return OC_STACK_ERROR;
+}
void DeleteClientCBList() {
ClientCB* out;
#include <string.h>
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "logger.h"
#include "debug.h"
#include "cJSON.h"
jsonbufferLength = strlen((const char *)jsonbuffer);
if(ret == OC_STACK_OK && jsonbufferLength)
{
- OCEntityHandlerResponse response;
- memset(&response, 0, sizeof(OCEntityHandlerResponse));
+ OCEntityHandlerResponse response = {0};
response.ehResult = OC_EH_OK;
response.payload = jsonbuffer;
response.payloadSize = jsonbufferLength + 1;
jsonbufferLength = strlen((const char *)jsonbuffer);
if(jsonbufferLength)
{
- OCEntityHandlerResponse response;
- memset(&response, 0, sizeof(OCEntityHandlerResponse));
+ OCEntityHandlerResponse response = {0};
response.ehResult = OC_EH_OK;
response.payload = jsonbuffer;
response.payloadSize = jsonbufferLength + 1;
#include "ocstackconfig.h"
#include "ocstackinternal.h"
#include "ocobserve.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "occoap.h"
#include "utlist.h"
#include "debug.h"
{
OCEntityHandlerResponse ehResponse = {0};
unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0};
- //we know it is the default entity handler
+ //This is effectively the implementation for the presence entity handler.
OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS,
if(result == OC_STACK_OK)
{
// we create the payload here
- if(resourceType)
+ if(resourceType && resourceType->resourcetypename)
{
sprintf((char *)presenceResBuf, "%u:%u:%s",
resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
{
sprintf((char *)presenceResBuf, "%u:%u", resPtr->sequenceNum, maxAge);
}
- memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
ehResponse.ehResult = OC_EH_OK;
ehResponse.payload = presenceResBuf;
ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1;
uint8_t numSentNotification = 0;
OCServerRequest * request = NULL;
OCStackResult result = OC_STACK_ERROR;
- OCEntityHandlerResponse ehResponse;
- memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+ OCEntityHandlerResponse ehResponse = {0};
OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification"));
while(numIds)
{
ResourceObserver *obsNode = NULL;
- obsNode = (ResourceObserver *) OCMalloc(sizeof(ResourceObserver));
+ obsNode = (ResourceObserver *) OCCalloc(1, sizeof(ResourceObserver));
if (obsNode)
{
- memset(obsNode, 0, sizeof(ResourceObserver));
obsNode->observeId = obsId;
obsNode->resUri = (unsigned char *)OCMalloc(strlen(resUri)+1);
#include "ocstack.h"
#include "ocstackconfig.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "ocobserve.h"
#include "occollection.h"
#include "occoap.h"
else
{
if(resource->resourceProperties & OC_ACTIVE){
- SendPresenceNotification(resource->rsrcType);
+ SendPresenceNotification(NULL);
}
}
#endif
#include "ocstack.h"
#include "ocserverrequest.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
// Module Name
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
{
OCServerRequest * serverRequest = NULL;
- serverRequest = (OCServerRequest *) OCMalloc(sizeof(OCServerRequest) + reqTotalSize - 1);
+ serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1);
VERIFY_NON_NULL(serverRequest);
- memset(serverRequest, 0, sizeof(OCServerRequest) + reqTotalSize - 1);
-
serverRequest->coapID = coapID;
serverRequest->delayedResNeeded = delayedResNeeded;
serverRequest->secured = secured;
{
OCServerResponse * serverResponse = NULL;
- serverResponse = (OCServerResponse *) OCMalloc(sizeof(OCServerResponse));
+ serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
VERIFY_NON_NULL(serverResponse);
- memset(serverResponse, 0, sizeof(OCServerResponse));
serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
VERIFY_NON_NULL(serverResponse->payload);
OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
{
OCStackResult result = OC_STACK_ERROR;
- OCServerProtocolResponse protocolResponse;
- memset(&protocolResponse, 0, sizeof(OCServerProtocolResponse));
+ OCServerProtocolResponse protocolResponse = {0};
OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
//-----------------------------------------------------------------------------
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "occlientcb.h"
#include "ocobserve.h"
#include "ocrandom.h"
{
OCStackResult result = OC_STACK_ERROR;
ResourceObserver * observer = NULL;
- OCEntityHandlerRequest ehRequest;
- memset(&ehRequest, 0, sizeof(OCEntityHandlerRequest));
+ OCEntityHandlerRequest ehRequest = {0};
switch(status)
{
return OC_STACK_ERROR;
}
+ #ifdef WITH_PRESENCE
+ // Ensure that the TTL associated with ANY and ALL presence notifications originating from
+ // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
+ presenceResource.presenceTTL = 0;
+ #endif // WITH_PRESENCE
+
// Free memory dynamically allocated for resources
deleteAllResources();
ClientCB *clientCB = NULL;
unsigned char * requestUri = NULL;
unsigned char * resourceType = NULL;
- char * newURI = (char *)requiredUri;
+ char * newUri = (char *)requiredUri;
(void) referenceUri;
OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
#ifdef WITH_PRESENCE
if(method == OC_REST_PRESENCE)
{
- result = getResourceType(requiredUri, &resourceType, &newURI);
+ result = getResourceType(requiredUri, &resourceType, &newUri);
+ if(resourceType) {
+ OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+ }
+ else
+ {
+ OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+ }
if(result != OC_STACK_OK)
{
goto exit;
requestUri = (unsigned char *) OCMalloc(uriLen + 1);
if(requestUri)
{
- memcpy(requestUri, newURI, (uriLen + 1));
+ memcpy(requestUri, newUri, (uriLen + 1));
}
else
{
// with the request
OCGenerateCoAPToken(&token);
- if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri, resourceType))
+ if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
!= OC_STACK_OK)
{
result = OC_STACK_NO_MEMORY;
}
// Make call to OCCoAP layer
- result = OCDoCoAPResource(method, qos, &token, newURI, request, options, numOptions);
+ result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
exit:
- if(newURI != requiredUri)
+ if(newUri != requiredUri)
{
- OCFree(newURI);
+ OCFree(newUri);
}
if (result != OC_STACK_OK)
{
}
}
// Create the pointer and insert it into the resource list
- pointer = (OCResource *) OCMalloc(sizeof(OCResource));
+ pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
if (!pointer) {
goto exit;
}
- memset(pointer, 0, sizeof(OCResource));
pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
insertResource(pointer);
TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
// Create the resourcetype and insert it into the resource list
- pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+ pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
if (!pointer) {
goto exit;
}
- memset(pointer, 0, sizeof(OCResourceType));
// Set the resourceTypeName
size = strlen(resourceTypeName) + 1;
TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
// Create the resourceinterface and insert it into the resource list
- pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
+ pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
if (!pointer) {
goto exit;
}
- memset(pointer, 0, sizeof(OCResourceInterface));
// Set the resourceinterface name
size = strlen(resourceInterfaceName) + 1;
OCMethod method = OC_REST_NOMETHOD;
uint32_t maxAge = 0;
+ OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
+ #ifdef WITH_PRESENCE
+ if(handle == presenceResource.handle)
+ {
+ return OC_STACK_OK;
+ }
+ #endif // WITH_PRESENCE
VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
+
// Verify that the resource exists
resPtr = findResource ((OCResource *) handle);
- if (NULL == resPtr || myStackMode == OC_CLIENT)
+ if (NULL == resPtr)
{
return OC_STACK_NO_RESOURCE;
}
presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
//presenceResource.token = OCGenerateCoAPToken();
result = OCCreateResource(&presenceResource.handle,
- "core.presence",
+ OC_RSRVD_RESOURCE_TYPE_PRESENCE,
"core.r",
OC_PRESENCE_URI,
NULL,
while (pointer)
{
temp = pointer->next;
- deleteResource(pointer);
+ #ifdef WITH_PRESENCE
+ if(pointer != (OCResource *) presenceResource.handle)
+ {
+ #endif // WITH_PRESENCE
+ deleteResource(pointer);
+ #ifdef WITH_PRESENCE
+ }
+ #endif // WITH_PRESENCE
pointer = temp;
}
+
+ #ifdef WITH_PRESENCE
+ // Ensure that the last resource to be deleted is the presence resource. This allows for all
+ // presence notification attributed to their deletion to be processed.
+ deleteResource((OCResource *) presenceResource.handle);
+ #endif // WITH_PRESENCE
}
/**
if (temp == resource) {
// Invalidate all Resource Properties.
resource->resourceProperties = (OCResourceProperty) 0;
- OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
-
#ifdef WITH_PRESENCE
+ if(resource != (OCResource *) presenceResource.handle)
+ {
+ #endif // WITH_PRESENCE
+ OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
+ #ifdef WITH_PRESENCE
+ }
+
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType);
+ if(resource != (OCResource *) presenceResource.handle)
+ {
+ SendPresenceNotification(resource->rsrcType);
+ }
+ else
+ {
+ SendPresenceNotification(NULL);
+ }
}
- #endif
+ #endif
if (temp == headResource) {
headResource = temp->next;
}
/**
+ * Finds a resource type in an OCResourceType link-list.
+ *
+ * @param resourceTypeList - the link-list to be searched through
+ * @param resourceTypeName - the key to search for
+ *
+ * @return
+ * resourceType that matches the key (ie. resourceTypeName)
+ * NULL - either an invalid parameter or this function was unable to find the key.
+ */
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
+{
+ if(resourceTypeList && resourceTypeName)
+ {
+ OCResourceType * rtPointer = resourceTypeList;
+ while(resourceTypeName && rtPointer)
+ {
+ if(rtPointer->resourcetypename &&
+ strcmp(resourceTypeName, (const char *)
+ (rtPointer->resourcetypename)) == 0)
+ {
+ break;
+ }
+ rtPointer = rtPointer->next;
+ }
+ return rtPointer;
+ }
+ return NULL;
+}
+/**
* Insert a resource interface into a resource's resource interface linked list.
*
* @param resource - resource where resource interface is to be inserted
{
return OC_STACK_INVALID_PARAM;
}
- char * ptr = NULL;
char * leftToken = NULL;
- char * tempURI = (char *) OCMalloc(strlen(uri));
+ char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
if(!tempURI)
{
goto exit;
}
- ptr = tempURI;
strcpy(tempURI, uri);
leftToken = strtok((char *)tempURI, "?");
leftToken = strtok(NULL, "?");
}
- *newURI = ptr;
+ *newURI = tempURI;
return OC_STACK_OK;
OCResource::Ptr light = constructResourceObject(resource->host(),
"/light", false, lightTypes, ifaces);
+ if(!light)
+ {
+ std::cout << "Error: Light Resource Object construction returned null\n";
+ return;
+ }
+
std::vector<std::string> doorTypes = {"intel.fridge.door"};
OCResource::Ptr leftdoor = constructResourceObject(resource->host(),
"/door/left", false, doorTypes, ifaces);
+ if(!leftdoor)
+ {
+ std::cout << "Error: Left Door Resource Object construction returned null\n";
+ return;
+ }
+
OCResource::Ptr rightdoor = constructResourceObject(resource->host(),
"/door/right", false, doorTypes, ifaces);
+ if(!rightdoor)
+ {
+ std::cout << "Error: Right Door Resource Object construction returned null\n";
+ return;
+ }
+
OCResource::Ptr randomdoor = constructResourceObject(resource->host(),
"/door/random", false, doorTypes, ifaces);
+ if(!randomdoor)
+ {
+ std::cout << "Error: Random Door Resource Object construction returned null\n";
+ return;
+ }
// Set header options with API version and token
HeaderOptions headerOptions;
}
case 1:
{
- bool isOn;
+ bool isOn = false;
rep.getValue("on",isOn);
std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"<<std::endl;
}
case 2:
case 3:
{
- bool isOpen;
+ bool isOpen = false;
std::string side;
rep.getValue("open", isOpen);
rep.getValue("side", side);
#include <string>
#include <cstdlib>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.garage",
&foundResource);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException& e)
{
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
// Invoke createResource function of class light.
myGarage.createResource();
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the OCPlatform
// When OCPlatform destructor is invoked, internally we do Platform cleanup
+
+ return 0;
}
#CXX := clang
OUT_DIR := $(BUILD)
-DEPEND_DIR:= ../dependencies
-CEREAL_DIR:= $(DEPEND_DIR)/cereal
-
CXX_FLAGS.debug := -O0 -g3 -std=c++0x -Wall -pthread
CXX_FLAGS.release := -O3 -std=c++0x -Wall -pthread
CXX_INC += -I../csdk/ocrandom/include
CXX_INC += -I../csdk/logger/include
CXX_INC += -I../csdk/libcoap
-CXX_INC += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a
-I../../csdk/ocsocket/include \
-I../../csdk/ocrandom/include \
-I../../csdk/logger/include \
- -I../../dependencies/cereal/include
BOOST_LIBS=-lboost_program_options
#BOOST_LIBS=-L/usr/local/boost/lib/ -lboost_program_options # for boost libraries at the specified path
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
}
// Callback to presence
-void presenceHandler(OCStackResult result, const unsigned int nonce)
+void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)
{
+ std::cout << "Received presence notification from : " << hostAddress << std::endl;
std::cout << "In presenceHandler: ";
switch(result)
if(resourceURI == "/a/light")
{
curResource = resource;
- OCPlatform::OCPresenceHandle presenceHandle;
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
{
{
std::cout << "Created Platform..."<<std::endl;
- OCPlatform::OCPresenceHandle presenceHandle;
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
{
OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
}
- while(true)
- {
- // some operations
- }
+ //
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
myLightResource.createResource3();
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
// Find all resources
OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
#include <functional>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
std::cout << "2 : Create room resource with application collection entity handler.\n";
}
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
{
printUsage();
myRoomResource.createResources();
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
+
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
// Find all resources
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource,
OC::QualityOfService::LowQos);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
{
std::cout<< "Exception in main: "<<e.what()<<std::endl;
}
+
+ return 0;
}
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
}
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
{
PrintUsage();
myLight.addType(std::string("core.brightlight"));
myLight.addInterface(std::string("oc.mi.ll"));
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform::destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
}
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
{
PrintUsage();
myLight.addType(std::string("core.brightlight"));
myLight.addInterface(std::string("oc.mi.ll"));
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
void putResourceInfo(const HeaderOptions& headerOptions,
const OCRepresentation rep, const OCRepresentation rep2, const int eCode)
{
- bool m_isFoo;
- int m_barCount;
+ bool m_isFoo = false;
+ int m_barCount = 0;
std::cout << "In PutResourceInfo" << std::endl;
std::cout <<"Clientside Put response to get was: "<<std::endl;
const OCRepresentation rep,
const int eCode)
{
- bool m_isFoo;
- int m_barCount;
+ bool m_isFoo = false;
+ int m_barCount = 0;
std::cout << "In getResourceInfo" << std::endl;
std::cout<<"Clientside response to get was: "<<std::endl;
std::cout<<"result1:" << OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo",
foundResource1)<< std::endl;
- while(1)
- {
- // client1 related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
void client2()
"coap://224.0.1.187/oc/core?rt=core.foo",
foundResource2)<< std::endl;
- while(1)
- {
- // client2 related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
void server()
return;
}
- while(1)
- {
- // server related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
int main()
std::thread t2(client2);
t2.detach();
- while(1)
- {
- // server related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException& e)
{
#define BOOST_MPL_LIMIT_LIST_SIZE 30
#define BOOST_MPL_LIMIT_VECTOR_SIZE 30
#include <boost/variant.hpp>
-#include <cereal/external/rapidjson/document.h>
namespace OC
{
typedef std::function<OCEntityHandlerResult(
const std::shared_ptr<OCResourceRequest>)> EntityHandler;
- typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
+ typedef std::function<void(OCStackResult, const unsigned int,
+ const std::string&)> SubscribeCallback;
typedef std::function<void(const HeaderOptions&,
const OCRepresentation&, const int)> GetCallback;
#include <AttributeValue.h>
#include <StringConstants.h>
-// note: is there any way to move this later so that the implementers don't need to
-// reference them?
-#include <cereal/cereal.hpp>
-#include <cereal/types/map.hpp>
-#include <cereal/types/vector.hpp>
-#include <OicJsonSerializer.hpp>// Customized Cereal serializer, required for a few functions
-#include <cereal/types/utility.hpp>
-
#include <OCException.h>
+
+
+namespace cereal
+{
+ class access;
+}
+
namespace OC
{
private:
friend class cereal::access;
template <class Archive>
- void save(Archive& ar) const
- {
- if(m_types.size() > 0)
- {
- ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
- }
-
- if(m_interfaces.size()>0)
- {
- ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
- }
- }
+ void save(Archive& ar) const;
template<class Archive>
- void load(Archive& ar)
- {
- optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
- optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
- }
+ void load(Archive& ar);
std::vector<std::string>& m_types;
std::vector<std::string>& m_interfaces;
};
template<class Archive, class Val>
- static void optional_load(Archive& ar, Val&& v)
- {
- try
- {
- ar(v);
- }
- catch(cereal::Exception& e)
- {
- ar.setNextName(nullptr);
- // Loading a key that doesn't exist results in an exception
- // Since "Not Found" is a valid condition for us, we swallow
- // this exception and the archive will not load anything
- }
- }
- template<class Archive>
- void save(Archive& ar) const
- {
- // printed for all interface types
- if(!m_uri.empty())
- {
- ar(cereal::make_nvp(Key::URIKEY, m_uri));
- }
+ static void optional_load(Archive& ar, Val&& v);
- if((m_interfaceType == InterfaceType::None
- || m_interfaceType==InterfaceType::DefaultChild
- || m_interfaceType==InterfaceType::LinkChild)
- && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
- {
- // The Prop object requires that it refer to non-const vectors
- // so that it can alter them in the 'load' case. In the save case
- // (initiated here) it will not modify the object. So, to keep the
- // compiler happy, removing the 'const' context here is necessary.
- const std::vector<std::string>& rt(m_resourceTypes);
- const std::vector<std::string>& intf(m_interfaces);
- Prop temp(const_cast<std::vector<std::string>&>(rt),
- const_cast<std::vector<std::string>&>(intf));
- ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
- }
-
- // printed only for BatchChildren and DefaultParent
- if((m_interfaceType == InterfaceType::None
- || m_interfaceType == InterfaceType::BatchChild
- || m_interfaceType == InterfaceType::DefaultParent)
- && m_values.size()>0)
- {
- ar(cereal::make_nvp(Key::REPKEY, m_values));
- }
- }
+ template<class Archive>
+ void save(Archive& ar) const;
template<class Archive>
- void load(Archive& ar)
- {
- optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
- {
- Prop temp(m_resourceTypes, m_interfaces);
- optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
- }
- optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
- }
+ void load(Archive& ar);
private:
std::string m_uri;
};
} // namespace OC
-// code needed to serialize a string::Attribute value map
-namespace OC
-{
- namespace detail
- {
- template<class Archive>
- class WriteAttributeValue : public boost::static_visitor<>
- {
- public:
- WriteAttributeValue(const std::string& name, Archive& ar)
- :m_name(name), m_archive(ar)
- {}
-
- template<class T>
- void operator()(const T& value) const
- {
- m_archive(cereal::make_nvp(m_name, value));
- }
- private:
- std::string m_name;
- Archive& m_archive;
- };
- }
-}
-
-namespace cereal
-{
- // take no action when serializing the null type, because the 'save' below
- // doesn't use the visitor for this type.
- template <class Archive>
- void serialize(Archive&, OC::NullType t)
- {}
-
- template<class Archive>
- void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
- {
- for(const auto& kv : vals)
- {
- const auto& k = kv.first;
- const auto& v = kv.second;
-
- if(v.which() != OC::AttributeValueNullIndex)
- {
- OC::detail::WriteAttributeValue<Archive> writer(k,ar);
- boost::apply_visitor(writer, v);
- }
- else
- {
- ar.setNextName(k.c_str());
- ar.writeName();
- ar.saveValue();
- }
- }
- }
-
- template<class Archive>
- void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
- {
- ar.loadAttributeValues(vals);
- }
-}
#endif //__OCREPRESENTATION_H
{
// we swallow this exception, since it means the key
// doesn't exist, allowing these to be optional
+ ar.setNextName(nullptr);
}
try
ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
}
catch(cereal::Exception&)
- {}
+ {
+ ar.setNextName(nullptr);
+ }
try
{
ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
}
catch(cereal::Exception&)
- {}
+ {
+ ar.setNextName(nullptr);
+ }
try
{
ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
}
catch(cereal::Exception&)
- {}
+ {
+ ar.setNextName(nullptr);
+ }
}
bool m_observable;
m_loaded=true;
}
catch(cereal::Exception&)
- {}
+ {
+ ar.setNextName(nullptr);
+ }
try
{
ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
m_loaded=true;
}
catch(cereal::Exception&)
- {}
+ {
+ ar.setNextName(nullptr);
+ }
}
private:
std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
{
- uint8_t addr1;
- uint8_t addr2;
- uint8_t addr3;
- uint8_t addr4;
+ char stringAddress[DEV_ADDR_SIZE_MAX];
uint16_t port;
ostringstream os;
throw ResourceInitException(false, false, false, false, false, true);
}
- if(0== OCDevAddrToIPv4Addr(&m_address, &addr1, &addr2, &addr3, &addr4))
+ if(0== OCDevAddrToString(&m_address, stringAddress))
{
// nothing to do, successful case.
}
throw ResourceInitException(false, false, false, false, false, true);
}
- os<<static_cast<int>(addr1)<<'.'
- <<static_cast<int>(addr2)<<'.'
- <<static_cast<int>(addr3)<<'.'
- <<static_cast<int>(addr4);
+ os<<stringAddress;
if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
{
else
{
oclog() << "ConvertOCAddrToString() : Invalid Port"
- <<std::flush;
+ <<std::flush;
throw ResourceInitException(false, false, false, false, true, false);
}
//! Saves a const char * to the current node
void saveValue(char const * s) { itsWriter.String(s); }
- private:
- // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
- // special overloads to handle these cases.
-
- //! 32 bit signed long saving to current node
- template <class T> inline
- typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
- saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
-
- //! non 32 bit signed long saving to current node
- template <class T> inline
- typename std::enable_if<sizeof(T) != sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
- saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
-
- //! 32 bit unsigned long saving to current node
- template <class T> inline
- typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
- saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
-
- //! non 32 bit unsigned long saving to current node
- template <class T> inline
- typename std::enable_if<sizeof(T) != sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
- saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
-
public:
#ifdef _MSC_VER
//! MSVC only long overload to current node
typename std::enable_if<std::is_same<T, long>::value &&
!std::is_same<T, std::int32_t>::value &&
!std::is_same<T, std::int64_t>::value, void>::type
- saveValue( T t ){ saveLong( t ); }
+ saveValue( T t )
+ {
+ saveLong( t );
+ return t;
+ }
//! Serialize an unsigned long if it would not be caught otherwise
template <class T> inline
typename std::enable_if<std::is_same<T, unsigned long>::value &&
!std::is_same<T, std::uint32_t>::value &&
!std::is_same<T, std::uint64_t>::value, void>::type
- saveValue( T t ){ saveLong( t ); }
+ saveValue( T t )
+ {
+ saveLong( t );
+ return t;
+ }
#endif // _MSC_VER
//! Save exotic arithmetic as strings to current node
std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
ss << t;
saveValue( ss.str() );
+ return t;
}
//! Write the name of the upcoming node and prepare object/array state
basic_demo();
c_demo();
alternative_demo();
+ return 0;
}
}
else
{
+ delete context;
result = OC_STACK_ERROR;
}
return result;
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
return result;
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
}
else
{
+ delete ctx;
return OC_STACK_ERROR;
}
}
OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
- OCClientResponse* clientResponse)
+ OCClientResponse* clientResponse)
{
- ClientCallbackContext::SubscribePresenceContext* context =
- static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
- std::thread exec(context->callback, clientResponse->result, clientResponse->sequenceNumber);
+ char stringAddress[DEV_ADDR_SIZE_MAX];
+ ostringstream os;
+ uint16_t port;
- exec.detach();
+ if(OCDevAddrToString(clientResponse->addr, stringAddress) == 0 &&
+ OCDevAddrToPort(clientResponse->addr, &port) == 0)
+ {
+ os<<stringAddress<<":"<<port;
+
+ ClientCallbackContext::SubscribePresenceContext* context =
+ static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
+
+ std::thread exec(context->callback, clientResponse->result,
+ clientResponse->sequenceNumber, os.str());
+
+ exec.detach();
+ }
+ else
+ {
+ oclog() << "subscribePresenceCallback(): OCDevAddrToString() or OCDevAddrToPort() "
+ <<"failed"<< std::flush;
+ }
return OC_STACK_KEEP_TRANSACTION;
}
}
if(!cLock)
+ {
+ delete ctx;
return OC_STACK_ERROR;
+ }
return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
OC_LOW_QOS, &cbdata, NULL, 0);
pRequest->setRequestHandlerFlag(
OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
- OC::ObservationInfo observationInfo;
- observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
- observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
- pRequest->setObservationInfo(observationInfo);
+ if(entityHandlerRequest)
+ {
+ OC::ObservationInfo observationInfo;
+ observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
+ observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
+ pRequest->setObservationInfo(observationInfo);
+ }
}
}
/// @brief This file contains the implementation of classes and its members
/// related to OCRepresentation
+
+#include <OCRepresentation.h>
+
#include <cereal/cereal.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/utility.hpp>
+#include <OicJsonSerializer.hpp>
#include <algorithm>
-#include <OCRepresentation.h>
+
+// code needed to serialize a string::Attribute value map
+namespace OC
+{
+ namespace detail
+ {
+ template<class Archive>
+ class WriteAttributeValue : public boost::static_visitor<>
+ {
+ public:
+ WriteAttributeValue(const std::string& name, Archive& ar)
+ :m_name(name), m_archive(ar)
+ {}
+
+ template<class T>
+ void operator()(const T& value) const
+ {
+ m_archive(cereal::make_nvp(m_name, value));
+ }
+ private:
+ std::string m_name;
+ Archive& m_archive;
+ };
+ }
+}
+
+namespace cereal
+{
+ // take no action when serializing the null type, because the 'save' below
+ // doesn't use the visitor for this type.
+ template <class Archive>
+ void serialize(Archive&, OC::NullType t)
+ {}
+
+ template<class Archive>
+ void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
+ {
+ for(const auto& kv : vals)
+ {
+ const auto& k = kv.first;
+ const auto& v = kv.second;
+
+ if(v.which() != OC::AttributeValueNullIndex)
+ {
+ OC::detail::WriteAttributeValue<Archive> writer(k,ar);
+ boost::apply_visitor(writer, v);
+ }
+ else
+ {
+ ar.setNextName(k.c_str());
+ ar.writeName();
+ ar.saveValue();
+ }
+ }
+ }
+
+ template<class Archive>
+ void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
+ {
+ ar.loadAttributeValues(vals);
+ }
+}
+
namespace OC
{
typedef cereal::JSONOutputArchive OutputArchiveType;
}
}
+namespace OC
+{
+ template <class Archive, class Val>
+ void OCRepresentation::optional_load(Archive& ar, Val&& v)
+ {
+ try
+ {
+ ar(v);
+ }
+ catch(cereal::Exception& e)
+ {
+ ar.setNextName(nullptr);
+ // Loading a key that doesn't exist results in an exception
+ // Since "Not Found" is a valid condition for us, we swallow
+ // this exception and the archive will not load anything
+ }
+ }
+
+ template<class Archive>
+ void OCRepresentation::save(Archive& ar) const
+ {
+ // printed for all interface types
+ if(!m_uri.empty())
+ {
+ ar(cereal::make_nvp(Key::URIKEY, m_uri));
+ }
+
+ if((m_interfaceType == InterfaceType::None
+ || m_interfaceType==InterfaceType::DefaultChild
+ || m_interfaceType==InterfaceType::LinkChild)
+ && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+ {
+ // The Prop object requires that it refer to non-const vectors
+ // so that it can alter them in the 'load' case. In the save case
+ // (initiated here) it will not modify the object. So, to keep the
+ // compiler happy, removing the 'const' context here is necessary.
+ const std::vector<std::string>& rt(m_resourceTypes);
+ const std::vector<std::string>& intf(m_interfaces);
+ Prop temp(const_cast<std::vector<std::string>&>(rt),
+ const_cast<std::vector<std::string>&>(intf));
+ ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
+ }
+
+ // printed only for BatchChildren and DefaultParent
+ if((m_interfaceType == InterfaceType::None
+ || m_interfaceType == InterfaceType::BatchChild
+ || m_interfaceType == InterfaceType::DefaultParent)
+ && m_values.size()>0)
+ {
+ ar(cereal::make_nvp(Key::REPKEY, m_values));
+ }
+ }
+
+ template<class Archive>
+ void OCRepresentation::load(Archive& ar)
+ {
+ optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
+ {
+ Prop temp(m_resourceTypes, m_interfaces);
+ optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
+ }
+ optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
+ }
+
+ template<class Archive>
+ void OCRepresentation::Prop::save(Archive& ar) const
+ {
+ if(m_types.size() > 0)
+ {
+ ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+ }
+
+ if(m_interfaces.size()>0)
+ {
+ ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+ }
+ }
+
+ template<class Archive>
+ void OCRepresentation::Prop::load(Archive& ar)
+ {
+ optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+ optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+ }
+}
+
// note: the below is used to load an AttributeValue map out of JSON
namespace OC
{
ROOT_DIR:=$(PWD)
endif
-DEPEND_DIR:=$(ROOT_DIR)/../dependencies
-CEREAL_DIR:=$(DEPEND_DIR)/cereal
-
INC_DIRS := -I../include/
INC_DIRS += -I../oc_logger/include
INC_DIRS += -I../csdk/stack/include
INC_DIRS += -I../csdk/logger/include
INC_DIRS += -I../csdk/libcoap
INC_DIRS += -I$(GTEST_DIR)/include
-INC_DIRS += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a
cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE)
sample-app:
- cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE)
- cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/fan-control/fanclient release/
+ cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE)
+ cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libpmimpl.so $(PROTOCOL_ROOT)sample-app/linux/mqtt/
+ cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/mqtt/mqttclient release/
clean:
cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE) clean
cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE) clean
cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE) clean
- cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE) clean
- cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE) clean
+ cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE) clean
rm -rf release
--- /dev/null
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+ #include <cstdlib> // For std::size_t
+ #include <cassert> // For assert
+ #include <new> // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4).
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127) // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+ //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS,
+ //! this function is called to notify user about the error.
+ //! It must be defined by the user.
+ //! <br><br>
+ //! This function cannot return. If it does, the results are undefined.
+ //! <br><br>
+ //! A very simple definition might look like that:
+ //! <pre>
+ //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+ //! {
+ //! std::cout << "Parse error: " << what << "\n";
+ //! std::abort();
+ //! }
+ //! </pre>
+ //! \param what Human readable description of the error.
+ //! \param where Pointer to character data where error was detected.
+ void parse_error_handler(const char *what, void *where);
+}
+
+#else
+
+#include <exception> // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+ //! Parse error exception.
+ //! This exception is thrown by the parser when an error occurs.
+ //! Use what() function to get human-readable error message.
+ //! Use where() function to get a pointer to position within source text where error was detected.
+ //! <br><br>
+ //! If throwing exceptions by the parser is undesirable,
+ //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+ //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+ //! This function must be defined by the user.
+ //! <br><br>
+ //! This class derives from <code>std::exception</code> class.
+ class parse_error: public std::exception
+ {
+
+ public:
+
+ //! Constructs parse error
+ parse_error(const char *what, void *where)
+ : m_what(what)
+ , m_where(where)
+ {
+ }
+
+ //! Gets human readable description of error.
+ //! \return Pointer to null terminated description of the error.
+ virtual const char *what() const throw()
+ {
+ return m_what;
+ }
+
+ //! Gets pointer to character data where error happened.
+ //! Ch should be the same as char type of xml_document that produced the error.
+ //! \return Pointer to location within the parsed string where error occured.
+ template<class Ch>
+ Ch *where() const
+ {
+ return reinterpret_cast<Ch *>(m_where);
+ }
+
+ private:
+
+ const char *m_what;
+ void *m_where;
+
+ };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+ // Size of static memory block of memory_pool.
+ // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+ #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+ // Size of dynamic memory block of memory_pool.
+ // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+ #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+ // Memory allocation alignment.
+ // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+ // All memory allocations for nodes, attributes and strings will be aligned to this value.
+ // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+ #define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+ // Forward declarations
+ template<class Ch> class xml_node;
+ template<class Ch> class xml_attribute;
+ template<class Ch> class xml_document;
+
+ //! Enumeration listing all node types produced by the parser.
+ //! Use xml_node::type() function to query node type.
+ enum node_type
+ {
+ node_document, //!< A document node. Name and value are empty.
+ node_element, //!< An element node. Name contains element name. Value contains text of first data node.
+ node_data, //!< A data node. Name is empty. Value contains data text.
+ node_cdata, //!< A CDATA node. Name is empty. Value contains data text.
+ node_comment, //!< A comment node. Name is empty. Value contains comment text.
+ node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+ node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+ node_pi //!< A PI node. Name contains target. Value contains instructions.
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Parsing flags
+
+ //! Parse flag instructing the parser to not create data nodes.
+ //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_data_nodes = 0x1;
+
+ //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+ //! Can be combined with other flags by use of | operator.
+ //! Note that child data nodes of element node take precendence over its value when printing.
+ //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+ //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_element_values = 0x2;
+
+ //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+ //! By default zero terminators are placed, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_string_terminators = 0x4;
+
+ //! Parse flag instructing the parser to not translate entities in the source text.
+ //! By default entities are translated, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_entity_translation = 0x8;
+
+ //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+ //! By default, UTF-8 handling is enabled.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_utf8 = 0x10;
+
+ //! Parse flag instructing the parser to create XML declaration node.
+ //! By default, declaration node is not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_declaration_node = 0x20;
+
+ //! Parse flag instructing the parser to create comments nodes.
+ //! By default, comment nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_comment_nodes = 0x40;
+
+ //! Parse flag instructing the parser to create DOCTYPE node.
+ //! By default, doctype node is not created.
+ //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_doctype_node = 0x80;
+
+ //! Parse flag instructing the parser to create PI nodes.
+ //! By default, PI nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_pi_nodes = 0x100;
+
+ //! Parse flag instructing the parser to validate closing tag names.
+ //! If not set, name inside closing tag is irrelevant to the parser.
+ //! By default, closing tags are not validated.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_validate_closing_tags = 0x200;
+
+ //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+ //! By default, whitespace is not trimmed.
+ //! This flag does not cause the parser to modify source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_trim_whitespace = 0x400;
+
+ //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+ //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+ //! By default, whitespace is not normalized.
+ //! If this flag is specified, source text will be modified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_normalize_whitespace = 0x800;
+
+ // Compound flags
+
+ //! Parse flags which represent default behaviour of the parser.
+ //! This is always equal to 0, so that all other flags can be simply ored together.
+ //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+ //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
+ //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+ //! and using the flag will disable it.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_default = 0;
+
+ //! A combination of parse flags that forbids any modifications of the source text.
+ //! This also results in faster parsing. However, note that the following will occur:
+ //! <ul>
+ //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+ //! <li>entities will not be translated</li>
+ //! <li>whitespace will not be normalized</li>
+ //! </ul>
+ //! See xml_document::parse() function.
+ const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+
+ //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+
+ //! A combination of parse flags resulting in largest amount of data being extracted.
+ //! This usually results in slowest parsing.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internals
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Struct that contains lookup tables for the parser
+ // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+ template<int Dummy>
+ struct lookup_tables
+ {
+ static const unsigned char lookup_whitespace[256]; // Whitespace table
+ static const unsigned char lookup_node_name[256]; // Node name table
+ static const unsigned char lookup_text[256]; // Text table
+ static const unsigned char lookup_text_pure_no_ws[256]; // Text table
+ static const unsigned char lookup_text_pure_with_ws[256]; // Text table
+ static const unsigned char lookup_attribute_name[256]; // Attribute name table
+ static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_digits[256]; // Digits
+ static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters
+ };
+
+ // Find length of the string
+ template<class Ch>
+ inline std::size_t measure(const Ch *p)
+ {
+ const Ch *tmp = p;
+ while (*tmp)
+ ++tmp;
+ return tmp - p;
+ }
+
+ // Compare strings for equality
+ template<class Ch>
+ inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+ {
+ if (size1 != size2)
+ return false;
+ if (case_sensitive)
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (*p1 != *p2)
+ return false;
+ }
+ else
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+ return false;
+ }
+ return true;
+ }
+ }
+ //! \endcond
+
+ ///////////////////////////////////////////////////////////////////////
+ // Memory pool
+
+ //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+ //! In most cases, you will not need to use this class directly.
+ //! However, if you need to create nodes manually or modify names/values of nodes,
+ //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
+ //! Not only is this faster than allocating them by using <code>new</code> operator,
+ //! but also their lifetime will be tied to the lifetime of document,
+ //! possibly simplyfing memory management.
+ //! <br><br>
+ //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
+ //! You can also call allocate_string() function to allocate strings.
+ //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+ //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
+ //! or when the pool is destroyed.
+ //! <br><br>
+ //! It is also possible to create a standalone memory_pool, and use it
+ //! to allocate nodes, whose lifetime will not be tied to any document.
+ //! <br><br>
+ //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
+ //! Until static memory is exhausted, no dynamic memory allocations are done.
+ //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+ //! by using global <code>new[]</code> and <code>delete[]</code> operators.
+ //! This behaviour can be changed by setting custom allocation routines.
+ //! Use set_allocator() function to set them.
+ //! <br><br>
+ //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+ //! This value defaults to the size of pointer on target architecture.
+ //! <br><br>
+ //! To obtain absolutely top performance from the parser,
+ //! it is important that all nodes are allocated from a single, contiguous block of memory.
+ //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+ //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code>
+ //! to obtain best wasted memory to performance compromise.
+ //! To do it, define their values before rapidxml.hpp file is included.
+ //! \param Ch Character type of created nodes.
+ template<class Ch = char>
+ class memory_pool
+ {
+
+ public:
+
+ //! \cond internal
+ typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory
+ typedef void (free_func)(void *); // Type of user-defined function used to free memory
+ //! \endcond
+
+ //! Constructs empty pool with default allocator functions.
+ memory_pool()
+ : m_alloc_func(0)
+ , m_free_func(0)
+ {
+ init();
+ }
+
+ //! Destroys pool and frees all the memory.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Nodes allocated from the pool are no longer valid.
+ ~memory_pool()
+ {
+ clear();
+ }
+
+ //! Allocates a new node from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param type Type of node to create.
+ //! \param name Name to assign to the node, or 0 to assign no name.
+ //! \param value Value to assign to the node, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated node. This pointer will never be NULL.
+ xml_node<Ch> *allocate_node(node_type type,
+ const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+ xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+ if (name)
+ {
+ if (name_size > 0)
+ node->name(name, name_size);
+ else
+ node->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ node->value(value, value_size);
+ else
+ node->value(value);
+ }
+ return node;
+ }
+
+ //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param name Name to assign to the attribute, or 0 to assign no name.
+ //! \param value Value to assign to the attribute, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated attribute. This pointer will never be NULL.
+ xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+ xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+ if (name)
+ {
+ if (name_size > 0)
+ attribute->name(name, name_size);
+ else
+ attribute->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ attribute->value(value, value_size);
+ else
+ attribute->value(value);
+ }
+ return attribute;
+ }
+
+ //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+ //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+ //! \return Pointer to allocated char array. This pointer will never be NULL.
+ Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+ {
+ assert(source || size); // Either source or size (or both) must be specified
+ if (size == 0)
+ size = internal::measure(source) + 1;
+ Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+ if (source)
+ for (std::size_t i = 0; i < size; ++i)
+ result[i] = source[i];
+ return result;
+ }
+
+ //! Clones an xml_node and its hierarchy of child nodes and attributes.
+ //! Nodes and attributes are allocated from this memory pool.
+ //! Names and values are not cloned, they are shared between the clone and the source.
+ //! Result node can be optionally specified as a second parameter,
+ //! in which case its contents will be replaced with cloned source node.
+ //! This is useful when you want to clone entire document.
+ //! \param source Node to clone.
+ //! \param result Node to put results in, or 0 to automatically allocate result node
+ //! \return Pointer to cloned node. This pointer will never be NULL.
+ xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+ {
+ // Prepare result node
+ if (result)
+ {
+ result->remove_all_attributes();
+ result->remove_all_nodes();
+ result->type(source->type());
+ }
+ else
+ result = allocate_node(source->type());
+
+ // Clone name and value
+ result->name(source->name(), source->name_size());
+ result->value(source->value(), source->value_size());
+
+ // Clone child nodes and attributes
+ for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+ result->append_node(clone_node(child));
+ for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+ result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+ return result;
+ }
+
+ //! Clears the pool.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Any nodes or strings allocated from the pool will no longer be valid.
+ void clear()
+ {
+ while (m_begin != m_static_memory)
+ {
+ char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+ if (m_free_func)
+ m_free_func(m_begin);
+ else
+ delete[] m_begin;
+ m_begin = previous_begin;
+ }
+ init();
+ }
+
+ //! Sets or resets the user-defined memory allocation functions for the pool.
+ //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+ //! Allocation function must not return invalid pointer on failure. It should either throw,
+ //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
+ //! If it returns invalid pointer, results are undefined.
+ //! <br><br>
+ //! User defined allocation functions must have the following forms:
+ //! <br><code>
+ //! <br>void *allocate(std::size_t size);
+ //! <br>void free(void *pointer);
+ //! </code><br>
+ //! \param af Allocation function, or 0 to restore default function
+ //! \param ff Free function, or 0 to restore default function
+ void set_allocator(alloc_func *af, free_func *ff)
+ {
+ assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet
+ m_alloc_func = af;
+ m_free_func = ff;
+ }
+
+ private:
+
+ struct header
+ {
+ char *previous_begin;
+ };
+
+ void init()
+ {
+ m_begin = m_static_memory;
+ m_ptr = align(m_begin);
+ m_end = m_static_memory + sizeof(m_static_memory);
+ }
+
+ char *align(char *ptr)
+ {
+ std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+ return ptr + alignment;
+ }
+
+ char *allocate_raw(std::size_t size)
+ {
+ // Allocate
+ void *memory;
+ if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[]
+ {
+ memory = m_alloc_func(size);
+ assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+ }
+ else
+ {
+ memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+ if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+ RAPIDXML_PARSE_ERROR("out of memory", 0);
+#endif
+ }
+ return static_cast<char *>(memory);
+ }
+
+ void *allocate_aligned(std::size_t size)
+ {
+ // Calculate aligned pointer
+ char *result = align(m_ptr);
+
+ // If not enough memory left in current pool, allocate a new pool
+ if (result + size > m_end)
+ {
+ // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+ std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+ if (pool_size < size)
+ pool_size = size;
+
+ // Allocate
+ std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation
+ char *raw_memory = allocate_raw(alloc_size);
+
+ // Setup new pool in allocated memory
+ char *pool = align(raw_memory);
+ header *new_header = reinterpret_cast<header *>(pool);
+ new_header->previous_begin = m_begin;
+ m_begin = raw_memory;
+ m_ptr = pool + sizeof(header);
+ m_end = raw_memory + alloc_size;
+
+ // Calculate aligned pointer again using new pool
+ result = align(m_ptr);
+ }
+
+ // Update pool and return aligned pointer
+ m_ptr = result + size;
+ return result;
+ }
+
+ char *m_begin; // Start of raw memory making up current pool
+ char *m_ptr; // First free byte in current pool
+ char *m_end; // One past last available byte in current pool
+ char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory
+ alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used
+ free_func *m_free_func; // Free function, or 0 if default is to be used
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML base
+
+ //! Base class for xml_node and xml_attribute implementing common functions:
+ //! name(), name_size(), value(), value_size() and parent().
+ //! \param Ch Character type to use
+ template<class Ch = char>
+ class xml_base
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ // Construct a base with empty name, value and parent
+ xml_base()
+ : m_name(0)
+ , m_value(0)
+ , m_parent(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets name of the node.
+ //! Interpretation of name depends on type of node.
+ //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use name_size() function to determine length of the name.
+ //! \return Name of node, or empty string if node has no name.
+ Ch *name() const
+ {
+ return m_name ? m_name : nullstr();
+ }
+
+ //! Gets size of node name, not including terminator character.
+ //! This function works correctly irrespective of whether name is or is not zero terminated.
+ //! \return Size of node name, in characters.
+ std::size_t name_size() const
+ {
+ return m_name ? m_name_size : 0;
+ }
+
+ //! Gets value of node.
+ //! Interpretation of value depends on type of node.
+ //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use value_size() function to determine length of the value.
+ //! \return Value of node, or empty string if node has no value.
+ Ch *value() const
+ {
+ return m_value ? m_value : nullstr();
+ }
+
+ //! Gets size of node value, not including terminator character.
+ //! This function works correctly irrespective of whether value is or is not zero terminated.
+ //! \return Size of node value, in characters.
+ std::size_t value_size() const
+ {
+ return m_value ? m_value_size : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets name of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of name must be specified separately, because name does not have to be zero terminated.
+ //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! \param name Name of node to set. Does not have to be zero terminated.
+ //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+ void name(const Ch *name, std::size_t size)
+ {
+ m_name = const_cast<Ch *>(name);
+ m_name_size = size;
+ }
+
+ //! Sets name of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+ //! \param name Name of node to set. Must be zero terminated.
+ void name(const Ch *name)
+ {
+ this->name(name, internal::measure(name));
+ }
+
+ //! Sets value of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of value must be specified separately, because it does not have to be zero terminated.
+ //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! <br><br>
+ //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+ //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+ //! \param value value of node to set. Does not have to be zero terminated.
+ //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+ void value(const Ch *value, std::size_t size)
+ {
+ m_value = const_cast<Ch *>(value);
+ m_value_size = size;
+ }
+
+ //! Sets value of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+ //! \param value Vame of node to set. Must be zero terminated.
+ void value(const Ch *value)
+ {
+ this->value(value, internal::measure(value));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets node parent.
+ //! \return Pointer to parent node, or 0 if there is no parent.
+ xml_node<Ch> *parent() const
+ {
+ return m_parent;
+ }
+
+ protected:
+
+ // Return empty string
+ static Ch *nullstr()
+ {
+ static Ch zero = Ch('\0');
+ return &zero;
+ }
+
+ Ch *m_name; // Name of node, or 0 if no name
+ Ch *m_value; // Value of node, or 0 if no value
+ std::size_t m_name_size; // Length of node name, or undefined of no name
+ std::size_t m_value_size; // Length of node value, or undefined if no value
+ xml_node<Ch> *m_parent; // Pointer to parent node, or 0 if none
+
+ };
+
+ //! Class representing attribute node of XML document.
+ //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+ //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
+ //! Thus, this text must persist in memory for the lifetime of attribute.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_attribute: public xml_base<Ch>
+ {
+
+ friend class xml_node<Ch>;
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty attribute with the specified type.
+ //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+ xml_attribute()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which attribute is a child.
+ //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ if (xml_node<Ch> *node = this->parent())
+ {
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+ else
+ return 0;
+ }
+
+ //! Gets previous attribute, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_prev_attribute : 0;
+ }
+
+ //! Gets next attribute, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_next_attribute : 0;
+ }
+
+ private:
+
+ xml_attribute<Ch> *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+ xml_attribute<Ch> *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML node
+
+ //! Class representing a node of XML document.
+ //! Each node may have associated name and value strings, which are available through name() and value() functions.
+ //! Interpretation of name and value depends on type of the node.
+ //! Type of node can be determined by using type() function.
+ //! <br><br>
+ //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
+ //! Thus, this text must persist in the memory for the lifetime of node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_node: public xml_base<Ch>
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty node with the specified type.
+ //! Consider using memory_pool of appropriate document to allocate nodes manually.
+ //! \param type Type of node to construct.
+ xml_node(node_type type)
+ : m_type(type)
+ , m_first_node(0)
+ , m_first_attribute(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets type of node.
+ //! \return Type of node.
+ node_type type() const
+ {
+ return m_type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which node is a child.
+ //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+
+ //! Gets first child node, optionally matching node name.
+ //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+ if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_first_node;
+ }
+
+ //! Gets last child node, optionally matching node name.
+ //! Behaviour is undefined if node has no children.
+ //! Use first_node() to test if node has children.
+ //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(m_first_node); // Cannot query for last child if node has no children
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+ if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_last_node;
+ }
+
+ //! Gets previous sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_prev_sibling;
+ }
+
+ //! Gets next sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_next_sibling;
+ }
+
+ //! Gets first attribute of node, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute;
+ }
+
+ //! Gets last attribute of node, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute ? m_last_attribute : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets type of node.
+ //! \param type Type of node to set.
+ void type(node_type type)
+ {
+ m_type = type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node manipulation
+
+ //! Prepends a new child node.
+ //! The prepended child becomes the first child, and all existing children are moved one position back.
+ //! \param child Node to prepend.
+ void prepend_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_next_sibling = m_first_node;
+ m_first_node->m_prev_sibling = child;
+ }
+ else
+ {
+ child->m_next_sibling = 0;
+ m_last_node = child;
+ }
+ m_first_node = child;
+ child->m_parent = this;
+ child->m_prev_sibling = 0;
+ }
+
+ //! Appends a new child node.
+ //! The appended child becomes the last child.
+ //! \param child Node to append.
+ void append_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_prev_sibling = m_last_node;
+ m_last_node->m_next_sibling = child;
+ }
+ else
+ {
+ child->m_prev_sibling = 0;
+ m_first_node = child;
+ }
+ m_last_node = child;
+ child->m_parent = this;
+ child->m_next_sibling = 0;
+ }
+
+ //! Inserts a new child node at specified place inside the node.
+ //! All children after and including the specified node are moved one position back.
+ //! \param where Place where to insert the child, or 0 to insert at the back.
+ //! \param child Node to insert.
+ void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+ {
+ assert(!where || where->parent() == this);
+ assert(child && !child->parent() && child->type() != node_document);
+ if (where == m_first_node)
+ prepend_node(child);
+ else if (where == 0)
+ append_node(child);
+ else
+ {
+ child->m_prev_sibling = where->m_prev_sibling;
+ child->m_next_sibling = where;
+ where->m_prev_sibling->m_next_sibling = child;
+ where->m_prev_sibling = child;
+ child->m_parent = this;
+ }
+ }
+
+ //! Removes first child node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_first_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_first_node;
+ m_first_node = child->m_next_sibling;
+ if (child->m_next_sibling)
+ child->m_next_sibling->m_prev_sibling = 0;
+ else
+ m_last_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes last child of the node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_last_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_last_node;
+ if (child->m_prev_sibling)
+ {
+ m_last_node = child->m_prev_sibling;
+ child->m_prev_sibling->m_next_sibling = 0;
+ }
+ else
+ m_first_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes specified child from the node
+ // \param where Pointer to child to be removed.
+ void remove_node(xml_node<Ch> *where)
+ {
+ assert(where && where->parent() == this);
+ assert(first_node());
+ if (where == m_first_node)
+ remove_first_node();
+ else if (where == m_last_node)
+ remove_last_node();
+ else
+ {
+ where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+ where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all child nodes (but not attributes).
+ void remove_all_nodes()
+ {
+ for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+ node->m_parent = 0;
+ m_first_node = 0;
+ }
+
+ //! Prepends a new attribute to the node.
+ //! \param attribute Attribute to prepend.
+ void prepend_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_next_attribute = m_first_attribute;
+ m_first_attribute->m_prev_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_next_attribute = 0;
+ m_last_attribute = attribute;
+ }
+ m_first_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_prev_attribute = 0;
+ }
+
+ //! Appends a new attribute to the node.
+ //! \param attribute Attribute to append.
+ void append_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_prev_attribute = m_last_attribute;
+ m_last_attribute->m_next_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_prev_attribute = 0;
+ m_first_attribute = attribute;
+ }
+ m_last_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_next_attribute = 0;
+ }
+
+ //! Inserts a new attribute at specified place inside the node.
+ //! All attributes after and including the specified attribute are moved one position back.
+ //! \param where Place where to insert the attribute, or 0 to insert at the back.
+ //! \param attribute Attribute to insert.
+ void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+ {
+ assert(!where || where->parent() == this);
+ assert(attribute && !attribute->parent());
+ if (where == m_first_attribute)
+ prepend_attribute(attribute);
+ else if (where == 0)
+ append_attribute(attribute);
+ else
+ {
+ attribute->m_prev_attribute = where->m_prev_attribute;
+ attribute->m_next_attribute = where;
+ where->m_prev_attribute->m_next_attribute = attribute;
+ where->m_prev_attribute = attribute;
+ attribute->m_parent = this;
+ }
+ }
+
+ //! Removes first attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_first_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_first_attribute;
+ if (attribute->m_next_attribute)
+ {
+ attribute->m_next_attribute->m_prev_attribute = 0;
+ }
+ else
+ m_last_attribute = 0;
+ attribute->m_parent = 0;
+ m_first_attribute = attribute->m_next_attribute;
+ }
+
+ //! Removes last attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_last_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_last_attribute;
+ if (attribute->m_prev_attribute)
+ {
+ attribute->m_prev_attribute->m_next_attribute = 0;
+ m_last_attribute = attribute->m_prev_attribute;
+ }
+ else
+ m_first_attribute = 0;
+ attribute->m_parent = 0;
+ }
+
+ //! Removes specified attribute from node.
+ //! \param where Pointer to attribute to be removed.
+ void remove_attribute(xml_attribute<Ch> *where)
+ {
+ assert(first_attribute() && where->parent() == this);
+ if (where == m_first_attribute)
+ remove_first_attribute();
+ else if (where == m_last_attribute)
+ remove_last_attribute();
+ else
+ {
+ where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+ where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all attributes of node.
+ void remove_all_attributes()
+ {
+ for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+ attribute->m_parent = 0;
+ m_first_attribute = 0;
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Restrictions
+
+ // No copying
+ xml_node(const xml_node &);
+ void operator =(const xml_node &);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Data members
+
+ // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+ // This is required for maximum performance, as it allows the parser to omit initialization of
+ // unneded/redundant values.
+ //
+ // The rules are as follows:
+ // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+ // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+ // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+ node_type m_type; // Type of node; always valid
+ xml_node<Ch> *m_first_node; // Pointer to first child node, or 0 if none; always valid
+ xml_node<Ch> *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+ xml_attribute<Ch> *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid
+ xml_attribute<Ch> *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+ xml_node<Ch> *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+ xml_node<Ch> *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML document
+
+ //! This class represents root of the DOM hierarchy.
+ //! It is also an xml_node and a memory_pool through public inheritance.
+ //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+ //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
+ //! which are inherited from memory_pool.
+ //! To access root node of the document, use the document itself, as if it was an xml_node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+ {
+
+ public:
+
+ //! Constructs empty XML document
+ xml_document()
+ : xml_node<Ch>(node_document)
+ {
+ }
+
+ //! Parses zero-terminated XML string according to given flags.
+ //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+ //! The string must persist for the lifetime of the document.
+ //! In case of error, rapidxml::parse_error exception will be thrown.
+ //! <br><br>
+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+ //! Make sure that data is zero-terminated.
+ //! <br><br>
+ //! Document can be parsed into multiple times.
+ //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+ //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+ template<int Flags>
+ void parse(Ch *text)
+ {
+ assert(text);
+
+ // Remove current contents
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+
+ // Parse BOM, if any
+ parse_bom<Flags>(text);
+
+ // Parse children
+ while (1)
+ {
+ // Skip whitespace before node
+ skip<whitespace_pred, Flags>(text);
+ if (*text == 0)
+ break;
+
+ // Parse and append new child
+ if (*text == Ch('<'))
+ {
+ ++text; // Skip '<'
+ if (xml_node<Ch> *node = parse_node<Flags>(text))
+ this->append_node(node);
+ }
+ else
+ RAPIDXML_PARSE_ERROR("expected <", text);
+ }
+
+ }
+
+ //! Clears the document by deleting all nodes and clearing the memory pool.
+ //! All nodes owned by document pool are destroyed.
+ void clear()
+ {
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+ memory_pool<Ch>::clear();
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal character utility functions
+
+ // Detect whitespace character
+ struct whitespace_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect node name character
+ struct node_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect attribute name character
+ struct attribute_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA)
+ struct text_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_no_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_with_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pure_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Insert coded character, using UTF8 or 8-bit ASCII
+ template<int Flags>
+ static void insert_coded_character(Ch *&text, unsigned long code)
+ {
+ if (Flags & parse_no_utf8)
+ {
+ // Insert 8-bit ASCII character
+ // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else
+ {
+ // Insert UTF8 sequence
+ if (code < 0x80) // 1 byte sequence
+ {
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else if (code < 0x800) // 2 byte sequence
+ {
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xC0);
+ text += 2;
+ }
+ else if (code < 0x10000) // 3 byte sequence
+ {
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xE0);
+ text += 3;
+ }
+ else if (code < 0x110000) // 4 byte sequence
+ {
+ text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xF0);
+ text += 4;
+ }
+ else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+ {
+ RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+ }
+ }
+ }
+
+ // Skip characters until predicate evaluates to true
+ template<class StopPred, int Flags>
+ static void skip(Ch *&text)
+ {
+ Ch *tmp = text;
+ while (StopPred::test(*tmp))
+ ++tmp;
+ text = tmp;
+ }
+
+ // Skip characters until predicate evaluates to true while doing the following:
+ // - replacing XML character entity references with proper characters (' & " < > &#...;)
+ // - condensing whitespace sequences to single space character
+ template<class StopPred, class StopPredPure, int Flags>
+ static Ch *skip_and_expand_character_refs(Ch *&text)
+ {
+ // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+ if (Flags & parse_no_entity_translation &&
+ !(Flags & parse_normalize_whitespace) &&
+ !(Flags & parse_trim_whitespace))
+ {
+ skip<StopPred, Flags>(text);
+ return text;
+ }
+
+ // Use simple skip until first modification is detected
+ skip<StopPredPure, Flags>(text);
+
+ // Use translation skip
+ Ch *src = text;
+ Ch *dest = src;
+ while (StopPred::test(*src))
+ {
+ // If entity translation is enabled
+ if (!(Flags & parse_no_entity_translation))
+ {
+ // Test if replacement is needed
+ if (src[0] == Ch('&'))
+ {
+ switch (src[1])
+ {
+
+ // & '
+ case Ch('a'):
+ if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+ {
+ *dest = Ch('&');
+ ++dest;
+ src += 5;
+ continue;
+ }
+ if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+ {
+ *dest = Ch('\'');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // "
+ case Ch('q'):
+ if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+ {
+ *dest = Ch('"');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // >
+ case Ch('g'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('>');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // <
+ case Ch('l'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('<');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // &#...; - assumes ASCII
+ case Ch('#'):
+ if (src[2] == Ch('x'))
+ {
+ unsigned long code = 0;
+ src += 3; // Skip &#x
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 16 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ else
+ {
+ unsigned long code = 0;
+ src += 2; // Skip &#
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 10 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ if (*src == Ch(';'))
+ ++src;
+ else
+ RAPIDXML_PARSE_ERROR("expected ;", src);
+ continue;
+
+ // Something else
+ default:
+ // Ignore, just copy '&' verbatim
+ break;
+
+ }
+ }
+ }
+
+ // If whitespace condensing is enabled
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Test if condensing is needed
+ if (whitespace_pred::test(*src))
+ {
+ *dest = Ch(' '); ++dest; // Put single space in dest
+ ++src; // Skip first whitespace char
+ // Skip remaining whitespace chars
+ while (whitespace_pred::test(*src))
+ ++src;
+ continue;
+ }
+ }
+
+ // No replacement, only copy character
+ *dest++ = *src++;
+
+ }
+
+ // Return new end
+ text = src;
+ return dest;
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal parsing functions
+
+ // Parse BOM, if any
+ template<int Flags>
+ void parse_bom(Ch *&text)
+ {
+ // UTF-8?
+ if (static_cast<unsigned char>(text[0]) == 0xEF &&
+ static_cast<unsigned char>(text[1]) == 0xBB &&
+ static_cast<unsigned char>(text[2]) == 0xBF)
+ {
+ text += 3; // Skup utf-8 bom
+ }
+ }
+
+ // Parse XML declaration (<?xml...)
+ template<int Flags>
+ xml_node<Ch> *parse_xml_declaration(Ch *&text)
+ {
+ // If parsing of declaration is disabled
+ if (!(Flags & parse_declaration_node))
+ {
+ // Skip until end of declaration
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+
+ // Create declaration
+ xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+ // Skip whitespace before attributes or ?>
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse declaration attributes
+ parse_node_attributes<Flags>(text, declaration);
+
+ // Skip ?>
+ if (text[0] != Ch('?') || text[1] != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected ?>", text);
+ text += 2;
+
+ return declaration;
+ }
+
+ // Parse XML comment (<!--...)
+ template<int Flags>
+ xml_node<Ch> *parse_comment(Ch *&text)
+ {
+ // If parsing of comments is disabled
+ if (!(Flags & parse_comment_nodes))
+ {
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 3; // Skip '-->'
+ return 0; // Do not produce comment node
+ }
+
+ // Remember value start
+ Ch *value = text;
+
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Create comment node
+ xml_node<Ch> *comment = this->allocate_node(node_comment);
+ comment->value(value, text - value);
+
+ // Place zero terminator after comment value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip '-->'
+ return comment;
+ }
+
+ // Parse DOCTYPE
+ template<int Flags>
+ xml_node<Ch> *parse_doctype(Ch *&text)
+ {
+ // Remember value start
+ Ch *value = text;
+
+ // Skip to >
+ while (*text != Ch('>'))
+ {
+ // Determine character type
+ switch (*text)
+ {
+
+ // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+ // This works for all W3C test files except for 2 most wicked
+ case Ch('['):
+ {
+ ++text; // Skip '['
+ int depth = 1;
+ while (depth > 0)
+ {
+ switch (*text)
+ {
+ case Ch('['): ++depth; break;
+ case Ch(']'): --depth; break;
+ case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ default: break;
+ }
+ ++text;
+ }
+ break;
+ }
+
+ // Error on end of text
+ case Ch('\0'):
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+ // Other character, skip it
+ default:
+ ++text;
+
+ }
+ }
+
+ // If DOCTYPE nodes enabled
+ if (Flags & parse_doctype_node)
+ {
+ // Create a new doctype node
+ xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+ doctype->value(value, text - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 1; // skip '>'
+ return doctype;
+ }
+ else
+ {
+ text += 1; // skip '>'
+ return 0;
+ }
+
+ }
+
+ // Parse PI
+ template<int Flags>
+ xml_node<Ch> *parse_pi(Ch *&text)
+ {
+ // If creation of PI nodes is enabled
+ if (Flags & parse_pi_nodes)
+ {
+ // Create pi node
+ xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+ // Extract PI target name
+ Ch *name = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected PI target", text);
+ pi->name(name, text - name);
+
+ // Skip whitespace between pi target and pi
+ skip<whitespace_pred, Flags>(text);
+
+ // Remember start of pi
+ Ch *value = text;
+
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0'))
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Set pi value (verbatim, no entity expansion or whitespace normalization)
+ pi->value(value, text - value);
+
+ // Place zero terminator after name and value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ pi->name()[pi->name_size()] = Ch('\0');
+ pi->value()[pi->value_size()] = Ch('\0');
+ }
+
+ text += 2; // Skip '?>'
+ return pi;
+ }
+ else
+ {
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0'))
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+ }
+
+ // Parse and append data
+ // Return character that ends data.
+ // This is necessary because this character might have been overwritten by a terminating 0
+ template<int Flags>
+ Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+ {
+ // Backup to contents start if whitespace trimming is disabled
+ if (!(Flags & parse_trim_whitespace))
+ text = contents_start;
+
+ // Skip until end of data
+ Ch *value = text, *end;
+ if (Flags & parse_normalize_whitespace)
+ end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
+ else
+ end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+ // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+ if (Flags & parse_trim_whitespace)
+ {
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+ if (*(end - 1) == Ch(' '))
+ --end;
+ }
+ else
+ {
+ // Backup until non-whitespace character is found
+ while (whitespace_pred::test(*(end - 1)))
+ --end;
+ }
+ }
+
+ // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+ // Create new data node
+ if (!(Flags & parse_no_data_nodes))
+ {
+ xml_node<Ch> *data = this->allocate_node(node_data);
+ data->value(value, end - value);
+ node->append_node(data);
+ }
+
+ // Add data to parent node if no data exists yet
+ if (!(Flags & parse_no_element_values))
+ if (*node->value() == Ch('\0'))
+ node->value(value, end - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ Ch ch = *text;
+ *end = Ch('\0');
+ return ch; // Return character that ends data; this is required because zero terminator overwritten it
+ }
+
+ // Return character that ends data
+ return *text;
+ }
+
+ // Parse CDATA
+ template<int Flags>
+ xml_node<Ch> *parse_cdata(Ch *&text)
+ {
+ // If CDATA is disabled
+ if (Flags & parse_no_data_nodes)
+ {
+ // Skip until end of cdata
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 3; // Skip ]]>
+ return 0; // Do not produce CDATA node
+ }
+
+ // Skip until end of cdata
+ Ch *value = text;
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Create new cdata node
+ xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+ cdata->value(value, text - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip ]]>
+ return cdata;
+ }
+
+ // Parse element node
+ template<int Flags>
+ xml_node<Ch> *parse_element(Ch *&text)
+ {
+ // Create element node
+ xml_node<Ch> *element = this->allocate_node(node_element);
+
+ // Extract element name
+ Ch *name = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected element name", text);
+ element->name(name, text - name);
+
+ // Skip whitespace between element name and attributes or >
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse attributes, if any
+ parse_node_attributes<Flags>(text, element);
+
+ // Determine ending type
+ if (*text == Ch('>'))
+ {
+ ++text;
+ parse_node_contents<Flags>(text, element);
+ }
+ else if (*text == Ch('/'))
+ {
+ ++text;
+ if (*text != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text;
+ }
+ else
+ RAPIDXML_PARSE_ERROR("expected >", text);
+
+ // Place zero terminator after name
+ if (!(Flags & parse_no_string_terminators))
+ element->name()[element->name_size()] = Ch('\0');
+
+ // Return parsed element
+ return element;
+ }
+
+ // Determine node type, and parse it
+ template<int Flags>
+ xml_node<Ch> *parse_node(Ch *&text)
+ {
+ // Parse proper node type
+ switch (text[0])
+ {
+
+ // <...
+ default:
+ // Parse and append element node
+ return parse_element<Flags>(text);
+
+ // <?...
+ case Ch('?'):
+ ++text; // Skip ?
+ if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+ (text[1] == Ch('m') || text[1] == Ch('M')) &&
+ (text[2] == Ch('l') || text[2] == Ch('L')) &&
+ whitespace_pred::test(text[3]))
+ {
+ // '<?xml ' - xml declaration
+ text += 4; // Skip 'xml '
+ return parse_xml_declaration<Flags>(text);
+ }
+ else
+ {
+ // Parse PI
+ return parse_pi<Flags>(text);
+ }
+
+ // <!...
+ case Ch('!'):
+
+ // Parse proper subset of <! node
+ switch (text[1])
+ {
+
+ // <!-
+ case Ch('-'):
+ if (text[2] == Ch('-'))
+ {
+ // '<!--' - xml comment
+ text += 3; // Skip '!--'
+ return parse_comment<Flags>(text);
+ }
+ break;
+
+ // <![
+ case Ch('['):
+ if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
+ text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+ {
+ // '<![CDATA[' - cdata
+ text += 8; // Skip '![CDATA['
+ return parse_cdata<Flags>(text);
+ }
+ break;
+
+ // <!D
+ case Ch('D'):
+ if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
+ text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
+ whitespace_pred::test(text[8]))
+ {
+ // '<!DOCTYPE ' - doctype
+ text += 9; // skip '!DOCTYPE '
+ return parse_doctype<Flags>(text);
+ }
+ break;
+
+ default:
+ break;
+
+ } // switch
+
+ // Attempt to skip other, unrecognized node types starting with <!
+ ++text; // Skip !
+ while (*text != Ch('>'))
+ {
+ if (*text == 0)
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ ++text; // Skip '>'
+ return 0; // No node recognized
+
+ }
+ }
+
+ // Parse contents of the node - children, data etc.
+ template<int Flags>
+ void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all children and text
+ while (1)
+ {
+ // Skip whitespace between > and node contents
+ Ch *contents_start = text; // Store start of node contents before whitespace is skipped
+ skip<whitespace_pred, Flags>(text);
+ Ch next_char = *text;
+
+ // After data nodes, instead of continuing the loop, control jumps here.
+ // This is because zero termination inside parse_and_append_data() function
+ // would wreak havoc with the above code.
+ // Also, skipping whitespace after data nodes is unnecessary.
+ after_data_node:
+
+ // Determine what comes next: node closing, child node, data node, or 0?
+ switch (next_char)
+ {
+
+ // Node closing or child node
+ case Ch('<'):
+ if (text[1] == Ch('/'))
+ {
+ // Node closing
+ text += 2; // Skip '</'
+ if (Flags & parse_validate_closing_tags)
+ {
+ // Skip and validate closing tag name
+ Ch *closing_name = text;
+ skip<node_name_pred, Flags>(text);
+ if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+ RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+ }
+ else
+ {
+ // No validation, just skip name
+ skip<node_name_pred, Flags>(text);
+ }
+ // Skip remaining whitespace after node name
+ skip<whitespace_pred, Flags>(text);
+ if (*text != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text; // Skip '>'
+ return; // Node closed, finished parsing contents
+ }
+ else
+ {
+ // Child node
+ ++text; // Skip '<'
+ if (xml_node<Ch> *child = parse_node<Flags>(text))
+ node->append_node(child);
+ }
+ break;
+
+ // End of data - error
+ case Ch('\0'):
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+ // Data node
+ default:
+ next_char = parse_and_append_data<Flags>(node, text, contents_start);
+ goto after_data_node; // Bypass regular processing after data nodes
+
+ }
+ }
+ }
+
+ // Parse XML attributes of the node
+ template<int Flags>
+ void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all attributes
+ while (attribute_name_pred::test(*text))
+ {
+ // Extract attribute name
+ Ch *name = text;
+ ++text; // Skip first character of attribute name
+ skip<attribute_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected attribute name", name);
+
+ // Create new attribute
+ xml_attribute<Ch> *attribute = this->allocate_attribute();
+ attribute->name(name, text - name);
+ node->append_attribute(attribute);
+
+ // Skip whitespace after attribute name
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip =
+ if (*text != Ch('='))
+ RAPIDXML_PARSE_ERROR("expected =", text);
+ ++text;
+
+ // Add terminating zero after name
+ if (!(Flags & parse_no_string_terminators))
+ attribute->name()[attribute->name_size()] = 0;
+
+ // Skip whitespace after =
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip quote and remember if it was ' or "
+ Ch quote = *text;
+ if (quote != Ch('\'') && quote != Ch('"'))
+ RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text;
+
+ // Extract attribute value and expand char refs in it
+ Ch *value = text, *end;
+ const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes
+ if (quote == Ch('\''))
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+ else
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+
+ // Set attribute value
+ attribute->value(value, end - value);
+
+ // Make sure that end quote is present
+ if (*text != quote)
+ RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text; // Skip quote
+
+ // Add terminating zero after value
+ if (!(Flags & parse_no_string_terminators))
+ attribute->value()[attribute->value_size()] = 0;
+
+ // Skip whitespace after attribute value
+ skip<whitespace_pred, Flags>(text);
+ }
+ }
+
+ };
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Whitespace (space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
+ };
+
+ // Node name (anything but space \n \r \t / > ? \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) (anything but < \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
+ // (anything but < \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+ // (anything but < \0 & space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote (anything but ' \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote that does not require processing (anything but ' \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote (anything but " \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote that does not require processing (anything but " \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Digits (dec and hex, 255 denotes end of numeric character reference)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F
+ };
+
+ // Upper case conversion
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
+ {
+ // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F
+ };
+ }
+ //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#endif
--- /dev/null
+#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
+#define RAPIDXML_ITERATORS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
+
+#include "rapidxml.hpp"
+
+namespace rapidxml
+{
+
+ //! Iterator of child nodes of xml_node
+ template<class Ch>
+ class node_iterator
+ {
+
+ public:
+
+ typedef typename xml_node<Ch> value_type;
+ typedef typename xml_node<Ch> &reference;
+ typedef typename xml_node<Ch> *pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ node_iterator()
+ : m_node(0)
+ {
+ }
+
+ node_iterator(xml_node<Ch> *node)
+ : m_node(node->first_node())
+ {
+ }
+
+ reference operator *() const
+ {
+ assert(m_node);
+ return *m_node;
+ }
+
+ pointer operator->() const
+ {
+ assert(m_node);
+ return m_node;
+ }
+
+ node_iterator& operator++()
+ {
+ assert(m_node);
+ m_node = m_node->next_sibling();
+ return *this;
+ }
+
+ node_iterator operator++(int)
+ {
+ node_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ node_iterator& operator--()
+ {
+ assert(m_node && m_node->previous_sibling());
+ m_node = m_node->previous_sibling();
+ return *this;
+ }
+
+ node_iterator operator--(int)
+ {
+ node_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ bool operator ==(const node_iterator<Ch> &rhs)
+ {
+ return m_node == rhs.m_node;
+ }
+
+ bool operator !=(const node_iterator<Ch> &rhs)
+ {
+ return m_node != rhs.m_node;
+ }
+
+ private:
+
+ xml_node<Ch> *m_node;
+
+ };
+
+ //! Iterator of child attributes of xml_node
+ template<class Ch>
+ class attribute_iterator
+ {
+
+ public:
+
+ typedef typename xml_attribute<Ch> value_type;
+ typedef typename xml_attribute<Ch> &reference;
+ typedef typename xml_attribute<Ch> *pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ attribute_iterator()
+ : m_attribute(0)
+ {
+ }
+
+ attribute_iterator(xml_node<Ch> *node)
+ : m_attribute(node->first_attribute())
+ {
+ }
+
+ reference operator *() const
+ {
+ assert(m_attribute);
+ return *m_attribute;
+ }
+
+ pointer operator->() const
+ {
+ assert(m_attribute);
+ return m_attribute;
+ }
+
+ attribute_iterator& operator++()
+ {
+ assert(m_attribute);
+ m_attribute = m_attribute->next_attribute();
+ return *this;
+ }
+
+ attribute_iterator operator++(int)
+ {
+ attribute_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ attribute_iterator& operator--()
+ {
+ assert(m_attribute && m_attribute->previous_attribute());
+ m_attribute = m_attribute->previous_attribute();
+ return *this;
+ }
+
+ attribute_iterator operator--(int)
+ {
+ attribute_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ bool operator ==(const attribute_iterator<Ch> &rhs)
+ {
+ return m_attribute == rhs.m_attribute;
+ }
+
+ bool operator !=(const attribute_iterator<Ch> &rhs)
+ {
+ return m_attribute != rhs.m_attribute;
+ }
+
+ private:
+
+ xml_attribute<Ch> *m_attribute;
+
+ };
+
+}
+
+#endif
--- /dev/null
+#ifndef RAPIDXML_PRINT_HPP_INCLUDED
+#define RAPIDXML_PRINT_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
+
+#include "rapidxml.hpp"
+
+// Only include streams if not disabled
+#ifndef RAPIDXML_NO_STREAMS
+ #include <ostream>
+ #include <iterator>
+#endif
+
+namespace rapidxml
+{
+
+ ///////////////////////////////////////////////////////////////////////
+ // Printing flags
+
+ const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal
+
+ //! \cond internal
+ namespace internal
+ {
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Internal character operations
+
+ // Copy characters from given range to given output iterator
+ template<class OutIt, class Ch>
+ inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
+ {
+ while (begin != end)
+ *out++ = *begin++;
+ return out;
+ }
+
+ // Copy characters from given range to given output iterator and expand
+ // characters into references (< > ' " &)
+ template<class OutIt, class Ch>
+ inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
+ {
+ while (begin != end)
+ {
+ if (*begin == noexpand)
+ {
+ *out++ = *begin; // No expansion, copy character
+ }
+ else
+ {
+ switch (*begin)
+ {
+ case Ch('<'):
+ *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
+ break;
+ case Ch('>'):
+ *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
+ break;
+ case Ch('\''):
+ *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
+ break;
+ case Ch('"'):
+ *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
+ break;
+ case Ch('&'):
+ *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
+ break;
+ default:
+ *out++ = *begin; // No expansion, copy character
+ }
+ }
+ ++begin; // Step to next character
+ }
+ return out;
+ }
+
+ // Fill given output iterator with repetitions of the same character
+ template<class OutIt, class Ch>
+ inline OutIt fill_chars(OutIt out, int n, Ch ch)
+ {
+ for (int i = 0; i < n; ++i)
+ *out++ = ch;
+ return out;
+ }
+
+ // Find character
+ template<class Ch, Ch ch>
+ inline bool find_char(const Ch *begin, const Ch *end)
+ {
+ while (begin != end)
+ if (*begin++ == ch)
+ return true;
+ return false;
+ }
+
+ template<class OutIt, class Ch>
+ inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
+
+ // Print children of the node
+ template<class OutIt, class Ch>
+ inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
+ out = print_node(out, child, flags, indent);
+ return out;
+ }
+
+ // Print attributes of the node
+ template<class OutIt, class Ch>
+ inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
+ {
+ for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+ {
+ if (attribute->name() && attribute->value())
+ {
+ // Print attribute name
+ *out = Ch(' '), ++out;
+ out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
+ *out = Ch('='), ++out;
+ // Print attribute value using appropriate quote type
+ if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
+ {
+ *out = Ch('\''), ++out;
+ out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+ *out = Ch('\''), ++out;
+ }
+ else
+ {
+ *out = Ch('"'), ++out;
+ out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+ *out = Ch('"'), ++out;
+ }
+ }
+ }
+ return out;
+ }
+
+ // Print data node
+ template<class OutIt, class Ch>
+ inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_data);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+ return out;
+ }
+
+ // Print data node
+ template<class OutIt, class Ch>
+ inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_cdata);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'); ++out;
+ *out = Ch('!'); ++out;
+ *out = Ch('['); ++out;
+ *out = Ch('C'); ++out;
+ *out = Ch('D'); ++out;
+ *out = Ch('A'); ++out;
+ *out = Ch('T'); ++out;
+ *out = Ch('A'); ++out;
+ *out = Ch('['); ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch(']'); ++out;
+ *out = Ch(']'); ++out;
+ *out = Ch('>'); ++out;
+ return out;
+ }
+
+ // Print element node
+ template<class OutIt, class Ch>
+ inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_element);
+
+ // Print element name and attributes, if any
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
+ out = print_attributes(out, node, flags);
+
+ // If node is childless
+ if (node->value_size() == 0 && !node->first_node())
+ {
+ // Print childless node tag ending
+ *out = Ch('/'), ++out;
+ *out = Ch('>'), ++out;
+ }
+ else
+ {
+ // Print normal node tag ending
+ *out = Ch('>'), ++out;
+
+ // Test if node contains a single data node only (and no other nodes)
+ xml_node<Ch> *child = node->first_node();
+ if (!child)
+ {
+ // If node has no children, only print its value without indenting
+ out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+ }
+ else if (child->next_sibling() == 0 && child->type() == node_data)
+ {
+ // If node has a sole data child, only print its value without indenting
+ out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
+ }
+ else
+ {
+ // Print all children with full indenting
+ if (!(flags & print_no_indenting))
+ *out = Ch('\n'), ++out;
+ out = print_children(out, node, flags, indent + 1);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ }
+
+ // Print node end
+ *out = Ch('<'), ++out;
+ *out = Ch('/'), ++out;
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
+ *out = Ch('>'), ++out;
+ }
+ return out;
+ }
+
+ // Print declaration node
+ template<class OutIt, class Ch>
+ inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ // Print declaration start
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('?'), ++out;
+ *out = Ch('x'), ++out;
+ *out = Ch('m'), ++out;
+ *out = Ch('l'), ++out;
+
+ // Print attributes
+ out = print_attributes(out, node, flags);
+
+ // Print declaration end
+ *out = Ch('?'), ++out;
+ *out = Ch('>'), ++out;
+
+ return out;
+ }
+
+ // Print comment node
+ template<class OutIt, class Ch>
+ inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_comment);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('!'), ++out;
+ *out = Ch('-'), ++out;
+ *out = Ch('-'), ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch('-'), ++out;
+ *out = Ch('-'), ++out;
+ *out = Ch('>'), ++out;
+ return out;
+ }
+
+ // Print doctype node
+ template<class OutIt, class Ch>
+ inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_doctype);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('!'), ++out;
+ *out = Ch('D'), ++out;
+ *out = Ch('O'), ++out;
+ *out = Ch('C'), ++out;
+ *out = Ch('T'), ++out;
+ *out = Ch('Y'), ++out;
+ *out = Ch('P'), ++out;
+ *out = Ch('E'), ++out;
+ *out = Ch(' '), ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch('>'), ++out;
+ return out;
+ }
+
+ // Print pi node
+ template<class OutIt, class Ch>
+ inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_pi);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('?'), ++out;
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
+ *out = Ch(' '), ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch('?'), ++out;
+ *out = Ch('>'), ++out;
+ return out;
+ }
+ ///////////////////////////////////////////////////////////////////////////
+ // Internal printing operations
+
+ // Print node
+ template<class OutIt, class Ch>
+ inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ // Print proper node type
+ switch (node->type())
+ {
+
+ // Document
+ case node_document:
+ out = print_children(out, node, flags, indent);
+ break;
+
+ // Element
+ case node_element:
+ out = print_element_node(out, node, flags, indent);
+ break;
+
+ // Data
+ case node_data:
+ out = print_data_node(out, node, flags, indent);
+ break;
+
+ // CDATA
+ case node_cdata:
+ out = print_cdata_node(out, node, flags, indent);
+ break;
+
+ // Declaration
+ case node_declaration:
+ out = print_declaration_node(out, node, flags, indent);
+ break;
+
+ // Comment
+ case node_comment:
+ out = print_comment_node(out, node, flags, indent);
+ break;
+
+ // Doctype
+ case node_doctype:
+ out = print_doctype_node(out, node, flags, indent);
+ break;
+
+ // Pi
+ case node_pi:
+ out = print_pi_node(out, node, flags, indent);
+ break;
+
+ // Unknown
+ default:
+ assert(0);
+ break;
+ }
+
+ // If indenting not disabled, add line break after node
+ if (!(flags & print_no_indenting))
+ *out = Ch('\n'), ++out;
+
+ // Return modified iterator
+ return out;
+ }
+ }
+ //! \endcond
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Printing
+
+ //! Prints XML to given output iterator.
+ //! \param out Output iterator to print to.
+ //! \param node Node to be printed. Pass xml_document to print entire document.
+ //! \param flags Flags controlling how XML is printed.
+ //! \return Output iterator pointing to position immediately after last character of printed text.
+ template<class OutIt, class Ch>
+ inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
+ {
+ return internal::print_node(out, &node, flags, 0);
+ }
+
+#ifndef RAPIDXML_NO_STREAMS
+
+ //! Prints XML to given output stream.
+ //! \param out Output stream to print to.
+ //! \param node Node to be printed. Pass xml_document to print entire document.
+ //! \param flags Flags controlling how XML is printed.
+ //! \return Output stream.
+ template<class Ch>
+ inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
+ {
+ print(std::ostream_iterator<Ch>(out), node, flags);
+ return out;
+ }
+
+ //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
+ //! \param out Output stream to print to.
+ //! \param node Node to be printed.
+ //! \return Output stream.
+ template<class Ch>
+ inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
+ {
+ return print(out, node);
+ }
+
+#endif
+
+}
+
+#endif
--- /dev/null
+#ifndef RAPIDXML_UTILS_HPP_INCLUDED
+#define RAPIDXML_UTILS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
+//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <fstream>
+#include <stdexcept>
+
+namespace rapidxml
+{
+
+ //! Represents data loaded from a file
+ template<class Ch = char>
+ class file
+ {
+
+ public:
+
+ //! Loads file into the memory. Data will be automatically destroyed by the destructor.
+ //! \param filename Filename to load.
+ file(const char *filename)
+ {
+ using namespace std;
+
+ // Open stream
+ basic_ifstream<Ch> stream(filename, ios::binary);
+ if (!stream)
+ throw runtime_error(string("cannot open file ") + filename);
+ stream.unsetf(ios::skipws);
+
+ // Determine stream size
+ stream.seekg(0, ios::end);
+ size_t size = stream.tellg();
+ stream.seekg(0);
+
+ // Load data and add terminating 0
+ m_data.resize(size + 1);
+ stream.read(&m_data.front(), static_cast<streamsize>(size));
+ m_data[size] = 0;
+ }
+
+ //! Loads file into the memory. Data will be automatically destroyed by the destructor
+ //! \param stream Stream to load from
+ file(std::basic_istream<Ch> &stream)
+ {
+ using namespace std;
+
+ // Load data and add terminating 0
+ stream.unsetf(ios::skipws);
+ m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
+ if (stream.fail() || stream.bad())
+ throw runtime_error("error reading stream");
+ m_data.push_back(0);
+ }
+
+ //! Gets file data.
+ //! \return Pointer to data of file.
+ Ch *data()
+ {
+ return &m_data.front();
+ }
+
+ //! Gets file data.
+ //! \return Pointer to data of file.
+ const Ch *data() const
+ {
+ return &m_data.front();
+ }
+
+ //! Gets file data size.
+ //! \return Size of file data, in characters.
+ std::size_t size() const
+ {
+ return m_data.size();
+ }
+
+ private:
+
+ std::vector<Ch> m_data; // File data
+
+ };
+
+ //! Counts children of node. Time complexity is O(n).
+ //! \return Number of children of node
+ template<class Ch>
+ inline std::size_t count_children(xml_node<Ch> *node)
+ {
+ xml_node<Ch> *child = node->first_node();
+ std::size_t count = 0;
+ while (child)
+ {
+ ++count;
+ child = child->next_sibling();
+ }
+ return count;
+ }
+
+ //! Counts attributes of node. Time complexity is O(n).
+ //! \return Number of attributes of node
+ template<class Ch>
+ inline std::size_t count_attributes(xml_node<Ch> *node)
+ {
+ xml_attribute<Ch> *attr = node->first_attribute();
+ std::size_t count = 0;
+ while (attr)
+ {
+ ++count;
+ attr = attr->next_attribute();
+ }
+ return count;
+ }
+
+}
+
+#endif
CXX = g++
CXX_FLAGS = -std=c++0x -Wall
-
-CPLUFF_DIR = ../../../lib/cpluff/libcpluff
+LIB = ../../../lib
+CPLUFF_DIR = $(LIB)/cpluff/libcpluff
SRC = ../../src/
CXX_INC = -I. -I$(CPLUFF_DIR)
+CXX_INC += -I$(LIB)/rapidxml
LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread
CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a
$(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp
-libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CPLUFF_DIR)/.libs/libcpluff.a
- $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CXX_LIBS) $(LINK_LIB)
+libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CPLUFF_DIR)/.libs/libcpluff.a
+ $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CXX_LIBS) $(LINK_LIB)
PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
$(CXX) $(CXX_INC) -fPIC -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManagerImpl.cpp
Plugin.o : $(SRC)Plugin.cpp
$(CXX) $(CXX_INC) -fPIC -c $(SRC)Plugin.cpp
+Config.o : $(SRC)Config.cpp
+ $(CXX) $(CXX_INC) -fPIC -c $(SRC)Config.cpp
+
CpluffAdapter.o : $(SRC)CpluffAdapter.cpp
$(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)CpluffAdapter.cpp
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics 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 Config.cpp
+
+/// @brief
+
+
+#include "Config.h"
+
+
+using namespace OIC;
+using namespace rapidxml;
+using namespace std;
+
+Config *Config::s_configinstance = NULL;
+
+Config::Config()
+{
+ if (loadConfigFile("./pluginmanager.xml") != PM_S_OK)
+ {
+ fprintf(stderr, "PM Configuration file is not exist current Folder.\n" );
+ exit(EXIT_FAILURE);
+ }
+}
+
+Config::~Config(void)
+{
+ s_configinstance->deleteinstance();
+ s_configinstance = NULL;
+}
+
+PMRESULT Config::loadConfigFile(const std::string configfilepath)
+{
+ // Read the xml file
+ std::ifstream xmlFile(configfilepath.c_str());
+ xml_document<> doc;
+ //into a vector
+ std::vector<char> buffer((istreambuf_iterator<char>(xmlFile)), istreambuf_iterator<char>());
+ buffer.push_back('\0');
+
+ // Parse the buffer using the xml file parsing library into doc
+ parsing(buffer, &doc);
+
+ // Find our root node
+ xml_node<> *root_node = doc.first_node("pluginManager");
+ xml_node<> *pluginInfo = root_node->first_node("pluginInfo");
+
+ getXmlData(pluginInfo, "pluginPath");
+ getXmlData(pluginInfo, "maxMEM");
+ getXmlData(pluginInfo, "version");
+ getXmlData(pluginInfo, "name");
+
+ return PM_S_OK;
+}
+
+PMRESULT Config::parsing(std::vector<char> buffer, xml_document<> *doc)
+{
+ // Parse the buffer using the xml file parsing library into doc
+ try
+ {
+ doc->parse<0>(&buffer[0]);
+ }
+ catch (rapidxml::parse_error err)
+ {
+ //print errors to screen
+ fprintf(stderr, "PM Configuration file parsing error \n");
+ exit(EXIT_FAILURE); //then exit
+ }
+ return PM_S_OK;
+}
+
+PMRESULT Config::getXmlData(xml_node<> *pluginInfo, std::string key)
+{
+ xml_attribute<> *iAttr = NULL;
+ std::string value = "";
+ if (iAttr = pluginInfo->first_attribute(key.c_str()))
+ {
+ value = iAttr->value();
+ setValue(key, value);
+ return PM_S_OK;
+ }
+ else
+ {
+ return PM_S_FALSE;
+ }
+}
+
+void Config::setValue(const std::string key, const std::string value)
+{
+ m_configurationMap.insert( std::pair<std::string, std::string>(key, value));
+}
+
+std::string Config::getValue(const std::string key)
+{
+ std::map<std::string, std::string>::iterator m_iterator;
+
+ m_iterator = m_configurationMap.find(key.c_str());
+
+ if (m_iterator != m_configurationMap.end())
+ {
+ return m_iterator->second;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+std::string Config::getVersion()
+{
+ std::map<std::string, std::string>::iterator m_iterator;
+
+ m_iterator = m_configurationMap.find("version");
+
+ if (m_iterator != m_configurationMap.end())
+ {
+ return m_iterator->second;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+std::string Config::getPluginPath()
+{
+ std::map<std::string, std::string>::iterator m_iterator;
+
+ m_iterator = m_configurationMap.find("pluginPath");
+
+ if (m_iterator != m_configurationMap.end())
+ {
+ return m_iterator->second;
+ }
+ else
+ {
+ return "";
+ }
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics 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 Config.h
+
+/// @brief
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include <map>
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rapidxml.hpp"
+#include <fstream>
+#include <vector>
+
+using namespace rapidxml;
+
+namespace OIC
+{
+
+ enum PMRESULT
+ {
+ PM_S_OK
+ , PM_S_FALSE
+ , PM_E_POINTER
+ , PM_E_OUTOFMEMORY
+ , PM_E_FAIL
+ , PM_E_NOINTERFACE
+ , PM_E_NOTIMPL
+ };
+ /**
+ * @brief Configuration class
+ *
+ *
+ */
+ class Config
+ {
+ public:
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ /**
+ *
+ * new Singleton pattern instance.
+ *
+ * @return config pointer Address.
+ */
+ static Config *Getinstance()
+ {
+ if (NULL == s_configinstance)
+ {
+ s_configinstance = new Config();
+ }
+
+ return s_configinstance;
+ }
+ std::string getPluginPath();
+ std::string getVersion();
+ std::string getValue(const std::string key);
+
+ private:
+ static Config *s_configinstance;
+ typedef std::map<std::string, std::string> configmap;
+ configmap m_configurationMap;
+ /**
+ * Constructor for Config.
+ * During construction time, configuration file will be loaded.
+ *
+ */
+ Config();
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~Config(void);
+
+ /**
+ * delete Singleton pattern instance.
+ */
+ static void deleteinstance()
+ {
+ if (NULL != s_configinstance)
+ {
+ delete s_configinstance;
+ s_configinstance = NULL;
+ }
+ }
+ void setValue(const std::string key, const std::string value);
+ PMRESULT loadConfigFile(const std::string configfilepath);
+ PMRESULT parsing(std::vector<char> buffer, xml_document<> *doc);
+ PMRESULT getXmlData( xml_node<> *pluginInfo, std::string key);
+ };
+}
+
+#endif
\ No newline at end of file
m_context = cp_create_context(&m_status);
m_cp_plugins = nullptr;
m_plugin = nullptr;
- registerAllPlugin("../../../plugins");
+
+ config = Config::Getinstance();
+ std::string pluginpath = config->getPluginPath();
+ if (pluginpath != "")
+ {
+ printf("Current path is %s\n", pluginpath.c_str());
+ }
+ else
+ {
+ fprintf(stderr, "Pluing path does not exist\n");
+ pluginpath = "";
+ }
+ registerAllPlugin(pluginpath);
}
CpluffAdapter::~CpluffAdapter(void)
{
cp_release_info(m_context, m_cp_plugins);
- m_thread_g.interrupt_all();
- m_thread_g.join_all();
+ //Auto plugin detection is disabled
+ //m_thread_g.interrupt_all();
+ //m_thread_g.join_all();
s_pinstance->deleteinstance();
s_pinstance = nullptr;
}
}
else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
{
- printf("cp_install_plugin failed\n");
+ if (m_status == CP_ERR_CONFLICT)
+ {
+ printf("Plugin is already installed or conflicts symbol.\n");
+ }
+ printf("cp_install_plugin failed : %d \n" , m_status);
+
return false;
}
File_list file_list;
getFileList(file_list, path);
File_list::iterator itr;
- int flag = FALSE;
-
+ int flag = TRUE;
for (itr = file_list.begin(); itr != file_list.end(); itr++)
{
if (itr->second == true)
}
}
std::string filename = filepath.substr(0, count );
- //char *temp_char = const_cast<char *>(filename.c_str());
- flag = installPlugin(filename);
- //printf("plugin file path %s \n", plugin->plugin_path);
+ if (!installPlugin(filename))
+ {
+ printf("installPlugin failed path : %s \n", filename.c_str());
+ }
}
}
}
else
{
- printPluginList(m_cp_plugins);
+ printPluginList();
}
for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
}
if (plugin_compare_flag)
{
- m_plugins.push_back(*plugin);
+ //Auto plugin detection is disabled
+ /*
try
{
boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
{
printf("thread throw exception\n");
}
+ */
+ m_plugins.push_back(*plugin);
delete(plugin);
}
//printf("plugin size = %d\n",m_plugins.size());
}
//non recursive
-
- flag = installPlugin(path);
-
- flag = loadPluginInfoToManager(path);
-
+ if (installPlugin(path))
+ {
+ flag = loadPluginInfoToManager(path);
+ }
return flag;
}
}
//recursive
-
- flag = findPluginRecursive(path);
-
- flag = loadPluginInfoToManager(path);
-
+ if (findPluginRecursive(path))
+ {
+ flag = loadPluginInfoToManager(path);
+ }
return flag;
}
}
}
-void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+void CpluffAdapter::printPluginList()
{
const char format[] = " %-30s %-15s %-15s %-20s\n";
printf("\n====== Plugins List ======\n");
}
return FALSE;
}
-
+//Auto plugin detection is disabled
+/*
void CpluffAdapter::observePluginPath(void *str)
{
//printf("start observePluginPath\n");
( void ) close( fd );
//printf("observePluginPath end\n");
}
-
+*/
const std::string CpluffAdapter::getState(const std::string plugID)
{
return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
#include <internal.h>
#include "Plugin.h"
+#include "Config.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
*/
const std::string getState(const std::string plugID);
+ /**
+ * print whole plugin info.
+ *
+ * @param cpluff plugins
+ */
+ void printPluginList();
+
/**
*
private:
+ Config *config;
typedef std::map<std::string, bool> File_list;
std::vector<Plugin> m_plugins;
cp_context_t *m_context;
cp_status_t m_status;
cp_plugin_info_t **m_cp_plugins;
cp_plugin_info_t *m_plugin;
- boost::thread m_file_detect_thread;
- boost::thread_group m_thread_g;
- std::string m_path;
+ //boost::thread_group m_thread_g;
static CpluffAdapter *s_pinstance;
/**
* @param plugin file path.
* @return void
*/
- void observePluginPath(void *);
+ //void observePluginPath(void *);
/**
bool getFileList(File_list &list, const std::string strDir);
/**
- * print whole plugin info.
- *
- * @param cpluff plugins
- */
- void printPluginList(cp_plugin_info_t **plugins);
-
- /**
* install plugin using c-pluff.
*
* @param Root path.
FelixAdapter::FelixAdapter()
{
-
+ config = Config::Getinstance();
+ std::string pluginpath = config->getPluginPath();
+ if (pluginpath != "")
+ {
+ printf("Current path is %s\n", pluginpath.c_str());
+ }
+ else
+ {
+ fprintf(stderr, "Pluing path is not exist\n");
+ pluginpath = "";
+ }
+ registerAllPlugin(pluginpath);
}
FelixAdapter::~FelixAdapter(void)
{
return FALSE;
}
-
+/*
void FelixAdapter::observePluginPath(void *str)
{
}
-
+*/
const std::string FelixAdapter::getState(const std::string plugID)
{
return "";
#include <internal.h>
#include "Plugin.h"
+#include "Config.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
private:
-
+ Config *config;
typedef std::map<std::string, bool> File_list;
std::vector<Plugin> m_plugins;
boost::thread m_file_detect_thread;
* @param plugin file path.
* @return void
*/
- void observePluginPath(void *);
+ //void observePluginPath(void *);
/**
* Get whole "SO" file list.
return false;
}
}
-
- std::vector<std::string> Plugin::getSupportedType(void)
- {
- return m_supportedType;
- }
-
- void Plugin::addSupportedType(const std::string rscType)
- {
- m_supportedType.push_back(rscType);
- }
}
*/
bool operator==(Plugin &plugin);
- /**
- * Get supported resourc type
- *
- *
- * @return vector of surported resource type
- */
- std::vector<std::string> getSupportedType(void);
- /**
- * Add supported resource type for a plugin
- *
- * @param resource type string
- * @return void
- *
- */
- void addSupportedType(const std::string rscType);
-
private:
std::map<std::string, AttributeValue> m_attributeMap;
std::vector<std::string> m_supportedType;
return pluginManagerImpl->stopPlugins(key, value);
}
-int PluginManager::startPlugins(Plugin *const plugin)
+int PluginManager::rescanPlugin()
{
- printf("PluginManager::startPlugins\n");
- return pluginManagerImpl->startPlugins(plugin);
+ return pluginManagerImpl->rescanPlugin();
}
-int PluginManager::stopPlugins(Plugin *const plugin)
+std::vector<Plugin> PluginManager::getPlugins(void)
{
- return pluginManagerImpl->stopPlugins(plugin);
+ return pluginManagerImpl->getAllPlugins();
}
-std::vector<Plugin> PluginManager::getPlugins(void)
+std::string PluginManager::getState(const std::string plugID)
{
- return pluginManagerImpl->getAllPlugins();
+ return pluginManagerImpl->getState(plugID);
}
\ No newline at end of file
int stopPlugins(const std::string key, const std::string value);
/**
- * Start plugin
- * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+ * Rescan Plugin.
+ * This function will call rescan function of plugins in the configuration folder
*
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- int startPlugins(Plugin *const plugin);
-
-
- /**
- * Stop Plugin.
- * This function will call stop function of plugin and unload dynamic plugin library from memory.
- *
- * @param Plugin
- * @return int, 1 is success, 0 is fail.
- */
- int stopPlugins(Plugin *const plugin);
+ int rescanPlugin();
/**
* Get Plugin list.
*/
std::vector<Plugin> getPlugins(void);
+ /**
+ * Get Plugin state.
+ *
+ * @param Plugin ID
+ * @return Plugin state.
+ */
+ std::string getState(const std::string plugID);
+
private:
PluginManagerImpl *pluginManagerImpl;
void (*destroy)(PluginManagerImpl *);
return flag;
}
+int PluginManagerImpl::rescanPlugin()
+{
+ Config *config = Config::Getinstance();
+ std::string pluginpath = config->getPluginPath();
+ if (pluginpath != "")
+ {
+ printf("Current path is %s\n", pluginpath.c_str());
+ }
+ else
+ {
+ fprintf(stderr, "Pluing path does not exist\n");
+ pluginpath = "";
+ }
+ int result = registerAllPlugin(pluginpath);
+ return result;
+}
+
std::vector<Plugin> &PluginManagerImpl::getAllPlugins(void)
{
* @param Plugin ID
* @return Plugin state.
*/
- std::string getState(const std::string plugID);
+ virtual std::string getState(const std::string plugID);
/**
* Start plugins by resource type
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- virtual int startPlugins(Plugin *const plugin);
+ int startPlugins(Plugin *const plugin);
/**
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- virtual int stopPlugins(Plugin *const plugin);
+ int stopPlugins(Plugin *const plugin);
+
+ /**
+ * Rescan Plugin.
+ * This function will call rescan function of plugins in the configuration folder
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ virtual int rescanPlugin();
/**
* get all plugins which currently registered.
-include ../../../../config.mk
-
CXX = g++
CXX_FLAGS = -std=c++0x -Wall -pthread
SRC_DIR = ../../src
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
CXX_INC := -I$(LIB_DIR)/include/
CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I$(BOOST_DIR)
CXX_INC += -I../../lib
CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC += -I../csdk/libcoap
+CXX_INC += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
-include config.mk
+include config.mk
.PHONY : really clean install
-include ../config.mk
-
# Set DESTDIR if it isn't given
DESTDIR?=/
int gObservation = 0;
void *ChangeFanRepresentation (void *param);
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
// Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'fanResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
// Forward declaring the entityHandler
-// void entityHandler(std::shared_ptr<OCResourceRequest> request,
-// std::shared_ptr<OCResourceResponse> response);
-
/// This class represents a single resource named 'fanResource'. This resource has
/// two simple properties named 'state' and 'power'
typedef struct plugin_data_t plugin_data_t;
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
// This will internally create and register the resource.
OCStackResult result = OCPlatform::registerResource(
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
OCResourceHandle resHandle;
private:
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
- OCEntityHandlerResult result = OC_EH_OK;
-
cout << "\tIn Server CPP entity handler:\n";
-
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if (request)
{
// Get the request type and request flag
}
if (requestFlag & RequestHandlerFlag::RequestFlag)
{
- cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+ cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
// If the request type is GET
if (requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if (response)
+ if (isSlowResponse) // Slow response case
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ static int startedThread = 0;
+ if (!startedThread)
+ {
+ std::thread t(handleSlowResponse, (void *)this, request);
+ startedThread = 1;
+ t.detach();
+ }
+ ehResult = OC_EH_SLOW;
+ }
+ else // normal response case.
+ {
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
}
else if (requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to PUT request
-
// Update the fanResource
put(rep);
-
- if (response)
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
-
}
else if (requestType == "POST")
{
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to POST request
-
OCRepresentation rep_post = post(rep);
-
- if (response)
+ pResponse->setResourceRepresentation(rep_post);
+ pResponse->setErrorCode(200);
+ if (rep_post.hasAttribute("createduri"))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(rep_post);
-
- if (rep_post.hasAttribute("createduri"))
- {
- result = OC_EH_RESOURCE_CREATED;
-
- response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
- }
-
+ pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+ pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
}
- // POST request operations
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
else if (requestType == "DELETE")
{
pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
return NULL;
}
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+ // This function handles slow response case
+ FanResource *fanPtr = (FanResource *) param;
+ // Induce a case for slow response by using sleep
+ std::cout << "SLOW response" << std::endl;
+ sleep (10);
+
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(fanPtr->get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ // Set the slow response flag back to false
+ isSlowResponse = false;
+ OCPlatform::sendResponse(pResponse);
+ return NULL;
+}
+
//int start_fanserver(void*) // 1
void *start_fanserver(void *d) // 2
{
- /*PlatformConfig cfg;
- cfg.ipAddress = "192.168.2.5";
- cfg.port = 56832;
- cfg.mode = ModeType::Server;
- cfg.serviceType = ServiceType::InProc;*/
- // PlatformConfig cfg
- // {
- // OC::ServiceType::InProc,
- // OC::ModeType::Server,
- // "192.168.2.5",
- // 56832,
- // OC::QualityOfService::NonConfirmable
- // };
-
- // Create PlatformConfig object
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
-
// Create PlatformConfig object
PlatformConfig cfg
{
OC::ServiceType::InProc,
- OC::ModeType::Server,
+ OC::ModeType::Both,
"0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
0, // Uses randomly available port
OC::QualityOfService::LowQos
printf("Mosquitto is working\n");
}
- //plugin_data_t *data = (plugin_data_t *)d;
- //OCPlatform *platform = (OCPlatform*)data->str;
- //myFanResource.m_platform = (OCPlatform*)data->str;
- //OCPlatform platform(cfg);
- // Invoke createResource function of class fan.
-
- //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
printf("Mosquitto Connection is done\n");
myFanResource.createResource();
- //myFanResource.addType(std::string("core.fan"));
- //myFanResource.addInterface(std::string("oc.mi.ll"));
// Get time of day
timer = time(NULL);
// Converts date/time to a structure
-include ../../../../config.mk
-
CXX = g++
CXX_FLAGS = -std=c++0x -Wall -pthread
SRC_DIR = ../../src
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
CXX_INC := -I$(LIB_DIR)/include/
CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I$(BOOST_DIR)
CXX_INC += -I../../lib
CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC += -I../csdk/libcoap
+CXX_INC += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
-include config.mk
+include config.mk
.PHONY : really clean install
-include ../config.mk
-
# Set DESTDIR if it isn't given
DESTDIR?=/
int gObservation = 0;
void *ChangeLightRepresentation (void *param);
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
// Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
// Forward declaring the entityHandler
// void entityHandler(std::shared_ptr<OCResourceRequest> request,
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
// This will internally create and register the resource.
OCStackResult result = OCPlatform::registerResource(
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
OCResourceHandle resHandle;
private:
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
- OCEntityHandlerResult result = OC_EH_OK;
-
cout << "\tIn Server CPP entity handler:\n";
-
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if (request)
{
// Get the request type and request flag
}
if (requestFlag & RequestHandlerFlag::RequestFlag)
{
- cout << "\t\trequestFlag : Request === Handle by LightServer\n";
+ cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
// If the request type is GET
if (requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if (response)
+ if (isSlowResponse) // Slow response case
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ static int startedThread = 0;
+ if (!startedThread)
+ {
+ std::thread t(handleSlowResponse, (void *)this, request);
+ startedThread = 1;
+ t.detach();
+ }
+ ehResult = OC_EH_SLOW;
+ }
+ else // normal response case.
+ {
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
}
else if (requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to PUT request
-
// Update the lightResource
put(rep);
-
- if (response)
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
-
}
else if (requestType == "POST")
{
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to POST request
-
OCRepresentation rep_post = post(rep);
-
- if (response)
+ pResponse->setResourceRepresentation(rep_post);
+ pResponse->setErrorCode(200);
+ if (rep_post.hasAttribute("createduri"))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(rep_post);
-
- if (rep_post.hasAttribute("createduri"))
- {
- result = OC_EH_RESOURCE_CREATED;
-
- response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
- }
-
+ pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+ pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
}
- // POST request operations
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
else if (requestType == "DELETE")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
return NULL;
}
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+ // This function handles slow response case
+ LightResource *lightPtr = (LightResource *) param;
+ // Induce a case for slow response by using sleep
+ std::cout << "SLOW response" << std::endl;
+ sleep (10);
+
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(lightPtr->get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ // Set the slow response flag back to false
+ isSlowResponse = false;
+ OCPlatform::sendResponse(pResponse);
+ return NULL;
+}
//int start_lightserver(void*) // 1
void *start_lightserver(void *d) // 2
{
- /*PlatformConfig cfg;
- cfg.ipAddress = "192.168.2.5";
- cfg.port = 56832;
- cfg.mode = ModeType::Server;
- cfg.serviceType = ServiceType::InProc;*/
- // PlatformConfig cfg
- // {
- // OC::ServiceType::InProc,
- // OC::ModeType::Server,
- // "192.168.2.5",
- // 56832,
- // OC::QualityOfService::NonConfirmable
- // };
-
- // Create PlatformConfig object
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
-
// Create PlatformConfig object
PlatformConfig cfg
{
OC::ServiceType::InProc,
- OC::ModeType::Server,
+ OC::ModeType::Both,
"0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
0, // Uses randomly available port
OC::QualityOfService::LowQos
printf("Mosquitto is working\n");
}
- //plugin_data_t *data = (plugin_data_t *)d;
- //OCPlatform *platform = (OCPlatform*)data->str;
- //myLightResource.m_platform = (OCPlatform*)data->str;
- //OCPlatform platform(cfg);
- // Invoke createResource function of class light.
-
- //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
printf("Mosquitto Connection is done\n");
myLightResource.createResource();
- //myLightResource.addType(std::string("core.light"));
- //myLightResource.addInterface(std::string("oc.mi.ll"));
// Get time of day
timer = time(NULL);
// Converts date/time to a structure
+This guide will help you setup your developing environment for Protocol plug-in Manager and Protocol plug-ins in Ubuntu.
+
+1. Preparings
+Before starting, following tools should be installed.
+
+Automake
+Automake is a tool for automatically generating Makefile.in files compiliant with the GNU Coding Standards. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+$ sudo apt-get install automake
+
+Libtool
+GNU libtool is a generic library support script. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+ $ sudo apt-get install libtool
+
+gettext
+GNU `gettext' utilities are a set of tools that provides a framework to help other GNU packages produce multi-lingual messages. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+ $ sudo apt-get install gettext
+
+Expat
+Expat is a stream-oriented XML parser library. This library is used for compiling C-Pluff open source which used in Plug-in Manager.
+ $ sudo apt-get install expat
+
+Building and Using Protocol Plug-in Manager
+
+Once the source code is downloaded into a specific folder, oic in this context, you may follow the steps to build and execute Protocol Plug-in Manager.
+The path for Protocol Plugin is as following;
+
+~/oic/oic-resource/service/protocol-plugin $_
+
+
+The Protocol Plug-in directory includes following sub directories;
+
+/plugin-manager Directory for Plug-in Manager
+/plugins Directory for Reference Plugins
+/lib Directory for Common Library
+/sample-app Directory for Iotivity Sample Application
+/doc Directory for Developers Document
+/build Directory for Building and Binary Release
+
+
+2. Compiling C-Pluff library
+Before building Protocol-Plugin Manager, C-Pluff library should be compiled as follows.
+
+~/oic/oic-service/protocol-plugin/lib/cpluff$ aclocal
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoconf
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoheader
+~/oic/oic-service/protocol-plugin/lib/cpluff$ automake
+~/oic/oic-service/protocol-plugin/lib/cpluff$ ./configure
+~/oic/oic-service/protocol-plugin/lib/cpluff$ make
+
+
+3. Run make
+By running make in the protocol-plugin path, protocol-plugin manager, all plugins and sample applications will be created.
+
+NOTE: To build plugins in 64-bit Ubuntu Linux, OCLib.a and libcoap.a library should be re-compiled with ?fPIC option.
+
+~/oic/oic-service/protocol-plugin/build/linux$make
+
+
+4. Using Plugins
This version of protocol plug-in source code has following functionality.
-1. provides plug-in manager which can register, unregister, start and stop plug-in library.
-2. provides plug-in library which can communicate with MQTT protocol FAN.
-3. provides OIC Sample Client which can turn on/off FAN.
+1) provides plug-in manager which can start and stop plug-in library.
+2) provides plug-in library which can communicate with MQTT protocol Fan and Light.
+3) provides OIC Sample Client which can get info about Fan and Light with configuration file(pluginmanager.xml).
So, to test a plug-in, follow below steps.
-1. Locate shared plug-in library and XML file in a specific folder.
-2. Register the plug-in with directory path input from plug-in manager sample.
-3. Start the plug-in from plug-in manager sample.
-4. Run OIC sample client.
-
-If you have any questions about protocol plug-in component, please contact with following addresses.
+1) Locate shared plug-in library and XML file in a specific folder.
+2) Register the plug-in with directory path input from plug-in manager sample.
+3) Start the plug-in from plug-in manager sample.
+4) Run OIC sample client.
+ ex)service/protocol-plugin/sample-app/linux/mqtt$./mqttclient
+ (mqtt broker is already installed in the local system.)
-kc7576.park@samsung.com
-heesung84.kim@samsung.com
-junho13.lee@samsung.com
-yh_.joo@samsung.com
\ No newline at end of file
LIB_DIR = ../../../../../resource
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
CXX_INC := -I$(LIB_DIR)/include/
CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I../../lib
CXX_INC += -I../../../lib/cpluff/libcpluff
CXX_INC += -I../../../plugin-manager/src
+CXX_INC += -I$(CEREAL_DIR)/include
+CXX_INC += -I../../../lib/rapidxml
LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread
-.PHONY: fanclient
+.PHONY: mqttclient
all: .PHONY
-fanclient: fanclient.o
- $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(CXX_LIBS) $(LINK_LIB)
+mqttclient: mqttclient.o
+ $(CXX) $(CXX_FLAGS) -o mqttclient mqttclient.o $(CXX_LIBS) $(LINK_LIB)
-fanclient.o: fanclient.cpp
- $(CXX) $(CXX_FLAGS) -c fanclient.cpp $(CXX_INC)
+mqttclient.o: mqttclient.cpp
+ $(CXX) $(CXX_FLAGS) -c mqttclient.cpp $(CXX_INC)
clean:
rm -f *.o
- rm -f fanclient
+ rm -f mqttclient
using namespace OC;
using namespace OIC;
-std::shared_ptr<OCResource> curResource;
+std::shared_ptr<OCResource> curFanResource;
+std::shared_ptr<OCResource> curLightResource;
static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
time_t timer; // Define the timer
if (observe_count() > 30)
{
std::cout << "Cancelling Observe..." << std::endl;
- OCStackResult result = curResource->cancelObserve();
+ OCStackResult result = curFanResource->cancelObserve();
std::cout << "Cancel result: " << result << std::endl;
sleep(10);
else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
std::cout << endl << "ObserveAll is used." << endl << endl;
- curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
+ //curFanResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
}
else
rep2.setValue("state", myfan.m_state);
rep2.setValue("power", myfan.m_power);
- curResource->post(rep2, QueryParamsMap(), &onPost2);
+ curFanResource->post(rep2, QueryParamsMap(), &onPost2);
}
else
{
std::cout << "\tpower: " << myfan.m_power << std::endl;
std::cout << "\tname: " << myfan.m_name << std::endl;
- postFanRepresentation(curResource);
+ postFanRepresentation(curFanResource);
}
else
{
std::cout << "\tpower: " << myfan.m_power << std::endl;
std::cout << "\tname: " << myfan.m_name << std::endl;
- putFanRepresentation(curResource);
+ putFanRepresentation(curFanResource);
}
else
{
// Callback to found resources
void foundResourceFan(std::shared_ptr<OCResource> resource)
{
- if (curResource)
+ if (curFanResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
}
if (resourceURI == "/a/fan")
{
- curResource = resource;
+ curFanResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getFanRepresentation(resource);
}
// Callback to found resources
void foundResourceLight(std::shared_ptr<OCResource> resource)
{
- if (curResource)
+ if (curLightResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
}
if (resourceURI == "/a/light")
{
- curResource = resource;
+ curLightResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getLightRepresentation(resource);
}
std::cout << "Finding Fan Resource... time : " << asctime(tblock) << std::endl;
while (1)
{
- // client1 related operations
+ std::cout << "Get Fan Resource....." << std::endl;
+ sleep(5);
+ getFanRepresentation(curFanResource);
}
}
while (1)
{
- // client2 related operations
+ std::cout << "Get Light Resource....." << std::endl;
+ sleep(5);
+ getLightRepresentation(curLightResource);
}
}
int main(int argc, char *argv[])
{
+ std::string name;
+ std::string key = "Name";
+ std::string state = "";
+ std::string id = "";
+
if (argc == 1)
{
OBSERVE_TYPE_TO_USE = ObserveType::Observe;
std::cout << "Created Platform..." << std::endl;
-
PluginManager *m_pm = new PluginManager();
+ std::cout << "==== 1st TEST CASE ===" << std::endl;
std::cout << "======================" << std::endl;
-
std::cout << "start light Plugin by Resource Type" << std::endl;
+
m_pm->startPlugins("ResourceType", "oic.light");
sleep(2);
+ std::cout << "\n==== 2nd TEST CASE =====" << std::endl;
std::cout << "======================" << std::endl;
- std::cout << "get Plugin List" << std::endl;
+ std::cout << "Get Plugin List\n" << std::endl;
std::vector<Plugin> user_plugin;
+
user_plugin = m_pm->getPlugins();
+
for (unsigned int i = 0; i < user_plugin.size(); i++)
{
- printf("value Name = %s\n", user_plugin[i].getName().c_str());
- printf("value ID = %s\n", user_plugin[i].getID().c_str());
+ std::cout << "value Name = " << user_plugin[i].getName() << std::endl;
+ std::cout << "value ID = " << user_plugin[i].getID() << std::endl;
+ id = user_plugin[i].getID();
}
-
+ std::cout << "\n===== 3rd TEST CASE =====" << std::endl;
std::cout << "======================" << std::endl;
- std::cout << "start Fan Plugin by Name" << std::endl;
- m_pm->startPlugins("Name", "mqtt-fan");
+ std::cout << "Start Fan Plugin by Name\n" << std::endl;
+
+ name = user_plugin[0].getName().c_str();
+ m_pm->startPlugins(key, name);
+
+ sleep(5);
+
+ std::cout << "\n====== 4th TEST CASE ======" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << "Get Plugin Status\n" << std::endl;
+
+ state = m_pm->getState(id);
+ std::cout << "last plugin status : " << state << std::endl;
+ std::cout << "sleep 15 seconds please add new plugin in the plugin folder " << std::endl;
+ sleep(15);
+
+ std::cout << "\n==== 5th TEST CASE ====" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << "Rescan Plugins.........\n" << std::endl;
+
+ m_pm->rescanPlugin();
+
+ std::cout << "\n==== 6th TEST CASE ====" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << "Try to start new resource type.........\n" << std::endl;
+ std::cout << "start oic.test resource" << std::endl;
+
+ sleep(5);
+
+ int flag = m_pm->startPlugins("ResourceType", "oic.test");
+
+ if (!flag)
+ std::cout << "There are no resouce type. Start plugin failed" << std::endl;
// Start each client in a seperate thread
-// std::thread t1(client1);
-// t1.detach();
-///*
-// sleep(5);
+ sleep(10);
+
+ std::cout << "\n====== 7th TEST CASE =======" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << " start client to find resource" << std::endl;
+
+ std::thread t1(client1);
+ t1.detach();
+
+ sleep(5);
+
// Start each client in a seperate thread
-// std::thread t2(client2);
-// t2.detach();
-//*/
+ std::thread t2(client2);
+ t2.detach();
+
while (true)
{
// some operations
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<pluginManager>
+ <pluginInfo
+ pluginPath="../../../plugins"
+ maxMEM="64M"
+ maxPlugin=""
+ version="1.0"
+ name="pluginmanager">
+ </pluginInfo>
+ <specailpluginInfo>
+ </specailpluginInfo>
+</pluginManager>
-
+-include ../../../build/linux/root_path.inc
-include ../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
INC_PATH=../../include
RST_NAME=release
+GAR=ar
+
# Insert your project name.
-TARGET=SDKlib
+TARGET=${SSM_LIB}
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I../../ -I${INC_PATH}/ -I${FD_SSMCORE}/include -I${FD_SSMCORE}/src -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB=
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@echo " "
${TARGET}: ${OBJLIST}
- @cp -Rdp ./*.o ./${RST_NAME}/
+ ${GAR} -r ./${RST_NAME}/$@ ./*.o
@cp -Rdp ${INC_PATH}/*.h ./${RST_NAME}/
@echo " "
{
private:
SSMReturn m_retResponse;
- OCPlatform *m_pPlatform;
CSemaphore m_sem;
/**
* @brief SoftSensorManager Resource.
// friend option. for callback from SSMResource
void onFoundResource(std::shared_ptr< OCResource > resource);
- void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
- void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
- void onRegisterQuery(const OCRepresentation &rep, const int eCode);
- void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
- void onObserve(const OCRepresentation &rep, const int &eCode);
+ void onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onReleaseQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int &eCode,
+ const int &sequenceNumber);
};
#endif /* RESOURCECLIENT_H_ */
--- /dev/null
+#include "SSMInterface.h"
+#include "SSMInterface/SSMCore.h"
+#include "Common/PlatformLayer.h"
+
+class SSMCoreEventReceiver : public IQueryEngineEvent
+{
+ public:
+ SSMCoreEventReceiver()
+ {
+ }
+
+ SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult)
+ {
+ SSMRESULT res = SSM_E_FAIL;
+
+ m_mtxListener.lock();
+
+ if (m_mapListener.find(cqid) == m_mapListener.end())
+ {
+ SSM_CLEANUP_ASSERT(res);
+ }
+
+ m_mapListener[cqid]->onQueryEngineEvent(cqid, pResult);
+
+ res = SSM_S_OK;
+
+CLEANUP:
+ m_mtxListener.unlock();
+ return res;
+ }
+
+ void lockListener()
+ {
+ m_mtxListener.lock();
+ }
+
+ void unlockListener()
+ {
+ m_mtxListener.unlock();
+ }
+
+ void addListener(IN int cqid, IN IQueryEngineEvent *pEngineEvent)
+ {
+ m_mapListener[cqid] = pEngineEvent;
+ }
+
+ void removeListener(IN int cqid)
+ {
+ m_mapListener.erase(cqid);
+ }
+
+ private:
+ CSimpleMutex m_mtxListener;
+ std::map<int, IQueryEngineEvent *> m_mapListener;
+};
+
+IQueryEngine *g_pQueryEngineInstance = NULL;
+SSMCoreEventReceiver *g_pEventReceiver = NULL;
+
+SSMInterface::SSMInterface()
+{
+ std::string xmlDescription = "<SSMCore>"
+ "<Device>"
+ "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
+ "<Name>MyPC</Name>"
+ "<Type>PC</Type>"
+ "</Device>"
+ "</SSMCore>";
+
+ SSMRESULT res = SSM_E_FAIL;
+
+ g_pEventReceiver = new SSMCoreEventReceiver();
+ SSM_CLEANUP_NULL_ASSERT(g_pEventReceiver);
+ SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
+ SSM_CLEANUP_ASSERT(StartSSMCore());
+ SSM_CLEANUP_ASSERT(CreateQueryEngine(&g_pQueryEngineInstance));
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->registerQueryEvent(g_pEventReceiver));
+CLEANUP:
+ ;
+}
+
+SSMInterface::~SSMInterface()
+{
+ SSMRESULT res = SSM_E_FAIL;
+
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->unregisterQueryEvent(g_pEventReceiver));
+ ReleaseQueryEngine(g_pQueryEngineInstance);
+ g_pQueryEngineInstance = NULL;
+ SSM_CLEANUP_ASSERT(StopSSMCore());
+ SSM_CLEANUP_ASSERT(TerminateSSMCore());
+
+CLEANUP:
+ SAFE_DELETE(g_pEventReceiver);
+}
+
+SSMRESULT SSMInterface::registerQuery(IN std::string queryString, IN IQueryEngineEvent *listener,
+ IN int &cqid)
+{
+ SSMRESULT res = SSM_E_FAIL;
+
+ g_pEventReceiver->lockListener();
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->executeContextQuery(queryString, &cqid));
+ g_pEventReceiver->addListener(cqid, listener);
+
+CLEANUP:
+ g_pEventReceiver->unlockListener();
+ return res;
+}
+
+SSMRESULT SSMInterface::unregisterQuery(IN int cqid)
+{
+ SSMRESULT res = SSM_E_FAIL;
+
+ g_pEventReceiver->lockListener();
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->killContextQuery(cqid));
+ g_pEventReceiver->removeListener(cqid);
+
+CLEANUP:
+ g_pEventReceiver->unlockListener();
+ return res;
+}
\ No newline at end of file
#define SSM_RESOURCE_TYPE = "core.SoftSensorManager"
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 5683
-#define COAP_MODE ModeType::Client
-#define COAP_SRVTYPE ServiceType::InProc
-
#define COAP_SERVER_ADDR "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
SSMClient::SSMClient()
{
m_sem.create(100000);
- m_pPlatform = NULL;
m_appListener = NULL;
m_retResponse = SSM_ERROR;
_findResource();
SSMClient::~SSMClient()
{
_releaseQueryEngine(m_queryEngineId);
- if (m_pPlatform)
- {
- delete m_pPlatform;
- m_pPlatform = NULL;
- }
}
void SSMClient::_findResource()
{
// Create PlatformConfig object
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+ PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+ "0.0.0.0", 0, OC::QualityOfService::LowQos);
// Create a OCPlatform instance.
// Note: Platform creation is synchronous call.
try
{
- m_pPlatform = new OCPlatform(cfg);
+ OCPlatform::Configure(cfg);
// Find all resources
OCStackResult result;
- if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
- std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
+ if ((result = OCPlatform::findResource("", COAP_SERVER_ADDR,
+ std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
!= OC_STACK_OK)
{
- delete m_pPlatform;
- m_pPlatform = NULL;
+ std::cout << "Faile to Find Resource... " << std::endl;
return;
}
+ std::cout << "Find Resource... " << std::endl;
m_sem.wait();
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("CreateQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- rep.setAttributeMap(requestAttributeMap);
+ rep.setValue("command", std::string("CreateQueryEngine"));
if (m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
+ std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
{
return;
}
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("ReleaseQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- rep.setAttributeMap(requestAttributeMap);
+ rep.setValue("command", std::string("ReleaseQueryEngine"));
+ rep.setValue("queryEngineId", queryEngineId);
m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2));
+ std::placeholders::_2, std::placeholders::_3));
m_sem.wait();
}
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues contextQueryValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("ExecuteContextQuery");
-
- requestAttributeMap["command"] = commandValue;
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- contextQueryValue.push_back(queryString);
-
- requestAttributeMap["contextQuery"] = contextQueryValue;
+ rep.setValue("command", std::string("ExecuteContextQuery"));
+ rep.setValue("queryEngineId", m_queryEngineId);
+ rep.setValue("contextQuery", queryString);
m_appListener = listener;
- rep.setAttributeMap(requestAttributeMap);
-
if (m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
+ std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
return SSM_ERROR_NETWORK;
m_sem.wait();
if (m_retResponse == SSM_SUCCESS)
{
- cqid = m_responseAttributeMap["CQID"].back();
+ cqid = m_responseAttributeMap["CQID"];
}
return m_retResponse;
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues cqidValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("KillContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- cqidValue.push_back(cqid);
-
- requestAttributeMap["CQID"] = cqidValue;
-
- rep.setAttributeMap(requestAttributeMap);
+ rep.setValue("command", std::string("KillContextQuery"));
+ rep.setValue("queryEngineId", m_queryEngineId);
+ rep.setValue("CQID", cqid);
if (m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
+ std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
return SSM_ERROR_NETWORK;
m_sem.wait();
m_sem.release();
}
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode)
{
if (eCode != 0)
{
goto CLEANUP;
}
- m_responseAttributeMap = rep.getAttributeMap();
- m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
- m_responseAttributeMap["queryEngineId"].pop_back();
+ m_queryEngineId = rep.getValue<std::string>("queryEngineId");
m_retResponse = SSM_SUCCESS;
CLEANUP: m_sem.release();
}
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode)
{
QueryParamsMap queryParamsMap;
}
m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
- std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
+ std::bind(&SSMClient::onObserve, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
m_retResponse = SSM_SUCCESS;
CLEANUP: m_sem.release();
}
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode)
{
if (eCode != 0)
{
CLEANUP: m_sem.release();
}
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onReleaseQueryEngine(const HeaderOptions &headerOptions,
+ const OCRepresentation &rep, const int eCode)
{
if (eCode != 0)
{
CLEANUP: m_sem.release();
}
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
+void SSMClient::onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int &eCode, const int &sequenceNumber)
{
SSMReturn ret = SSM_SUCCESS;
-
+-include ../../../build/linux/root_path.inc
-include ../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
RST_NAME=release
# Insert your project name.
-TARGET=SSMCoreUbuntu
+TARGET=${SSMCORE_LIB}
EXCLUDE_LIST=SSMCore_JNI.cpp
# C++ type Compile Flag define.
CXX=g++
-CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -DMODEL_DIRECTORY=${MODEL_DIR} -DHIGH_LOCATION=${HIGH_LOCATION} -ldl
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST} -I${SRC_PATH} -I${SRC_PATH}/Common -I${SRC_PATH}/QueryProcessor -I${SRC_PATH}/SensorProcessor -I${SRC_PATH}/SSMInterface
+CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -ldl
+CXX_INC=-I${INC_PATH}/ -I${SRC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB=-L""
CXX_SRCPATH=${wildcard ${SRC_PATH}/**/*.cpp}
# Linker FLAGS define.
LD_FLAGS=-std=c++0x -Wall -DLINUX
-# GAR=ar
-LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} -lpthread -ldl
+GAR=ar
+# LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} ${IOT_LOG_DIR}/lib/${IOT_LOG_LIB} -lpthread -ldl
# Force metatargets to build:
@echo "${MODEL_DIR}"
${TARGET}: ${GCC_OBJLIST} ${CXX_OBJLIST}
- $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}
- # ${GAR} -r ./${RST_NAME}/$@ ./*.o
+ # $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}
+ ${GAR} -r ./${RST_NAME}/$@ ./*.o
@echo " "
%.o : ${SRC_PATH}/**/%.c
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
+ cp -Rdp ${INC_PATH}/SSMInterface.h ${OUTPUTS_DIR}/
cp -Rdp ${SRC_PATH}/SSMInterface/SSMModelDefinition.h ${OUTPUTS_DIR}/
@echo "---------------- SSMCore Build Successful. ---------------"
@echo "Enter to ${RST_NAME} folder."
--- /dev/null
+#ifndef _SSMInterface_H_
+#define _SSMInterface_H_
+
+#include <string>
+#include <vector>
+
+enum SSMRESULT
+{
+ SSM_S_OK
+ , SSM_S_FALSE
+ , SSM_E_POINTER
+ , SSM_E_OUTOFMEMORY
+ , SSM_E_FAIL
+ , SSM_E_NOINTERFACE
+ , SSM_E_NOTIMPL
+};
+
+/**
+* @class IModelData
+* @brief IModelData Interface
+* This class represents context model data package
+*
+* @see
+*/
+class IModelData
+{
+ public:
+ /**
+ * @fn getDataId
+ * @brief Get affected DataId. ContextModel has plenty of data so \n
+ * returned data is matched from given condition
+ *
+ * @param None
+ *
+ * @return int
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual int getDataId() = 0;
+
+ /**
+ * @fn GetPropertyCount
+ * @brief ContextModel has at least one property that contains data \n
+ * property is described from its specification.
+ *
+ * @param None
+ *
+ * @return int
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual int getPropertyCount() = 0;
+
+ /**
+ * @fn getPropertyName
+ * @brief Retrieve propertyName
+ *
+ * @param [in] int propertyIndex - index of property to read
+ *
+ * @return std::string
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual std::string getPropertyName(int propertyIndex) = 0;
+
+ /**
+ * @fn getPropertyValue
+ * @brief Retrieve propertyValue
+ *
+ * @param [in] int propertyIndex - index of property to read
+ *
+ * @return std::string
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual std::string getPropertyValue(int propertyIndex) = 0;
+
+ /**
+ * @fn getPropertyValueByName
+ * @brief Retrieve propertyValue using given name
+ *
+ * @param [in] std::string propertyName - property name looking for
+ *
+ * @return std::string
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual std::string getPropertyValueByName(std::string propertyName) = 0;
+ protected:
+ virtual ~IModelData() {};
+};
+
+/**
+* @class IDataReader
+* @brief IDataReader Interface
+* This class represents context model data package's reader
+*
+* @see
+*/
+class IDataReader
+{
+ public:
+ /**
+ * @fn getAffectedModels
+ * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
+ *
+ * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT getAffectedModels(std::vector<std::string> *pAffectedModels) = 0;
+
+ /**
+ * @fn getModelDataCount
+ * @brief Get affected data count. There are multiple data can exist from given condition.
+ *
+ * @param [in] std::string modelName - affected ContextModel name
+ *
+ * @param [out] int *pDataCount - affected dataId count
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT getModelDataCount(std::string modelName, int *pDataCount) = 0;
+
+ /**
+ * @fn getModelData
+ * @brief Get actual Context Model data
+ *
+ * @param [in] std::string modelName - affected ContextModel name
+ *
+ *
+ * @param [in] int dataIndex - affected dataId index
+ *
+ *
+ * @param [out] IModelData **ppModelData - affected ContextModel data reader
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT getModelData(std::string modelName, int dataIndex, IModelData **ppModelData) = 0;
+ protected:
+ virtual ~IDataReader() {};
+};
+
+/**
+* @class IQueryEngineEvent
+* @brief IQueryEngineEvent Interface
+* This class represents Query Engine's event that contains results
+*
+* @see
+*/
+class IQueryEngineEvent
+{
+ public:
+ /**
+ * @fn onQueryEngineEvent
+ * @brief Transmit result of SSMCore to Application layer
+ *
+ * @param [in] int cqid - entered ContextQuery ID
+ *
+ * @param [in] IDataReader *pResult - result of SSMCore
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult) = 0;
+ protected:
+ virtual ~IQueryEngineEvent() {};
+};
+
+class SSMInterface
+{
+ public:
+ SSMInterface();
+ ~SSMInterface();
+
+ SSMRESULT registerQuery(std::string queryString, IQueryEngineEvent *listener, int &cqid);
+ SSMRESULT unregisterQuery(int cqid);
+};
+#endif
\ No newline at end of file
;
/**
- * @fn setCurrentDeviceInfo
- * @brief set device information
+ * @fn initRepository
+ * @brief initialize repository using given info
*
* @param [in] std::string name - Device name
* @param [in] std::string type - Device Type
* @param [in] std::string pathSoftSensors - SoftSensors Repository path
* @param [in] std::string pathDescription - SoftSensors Description path
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- virtual void setCurrentDeviceInfo(IN std::string name, IN std::string type,
- IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
+ virtual SSMRESULT initRepository(IN std::string name, IN std::string type,
+ IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
virtual SSMRESULT registerResourceFinderEvent(IN IResourceEvent *pResourceEvent) = 0;
virtual SSMRESULT startResourceFinder() = 0;
IEvent *pEvent) = 0;
};
-static const OID OID_IResponseReactor = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
+static const OID OID_ISensingEngine = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
/**
- * @class IResponseReactor
- * @brief Interface for implement of reactor pattern
- * Delegate requested context to context executor layer.
+ * @class ISensingEngine
+ * @brief Class for implementing main abstration of SensorProcessor
*
*
* @see
*/
-class IResponseReactor : public IBase
+class ISensingEngine : public IBase
, public IEvent
{
public:
* @exception
* @see
*/
- virtual void registerContext(TypeofEvent callType, ISSMResource *pSSMResouce, IEvent *pEvent) = 0;
+ virtual SSMRESULT registerContext(TypeofEvent callType, ISSMResource *pSSMResouce,
+ IEvent *pEvent) = 0;
/**
* @fn unregisterContext
* @exception
* @see
*/
- virtual void unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
- IEvent *pEvent) = 0;
+ virtual SSMRESULT unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+ IEvent *pEvent) = 0;
/**
* @fn getList
* @exception
* @see
*/
- virtual void getList(std::vector<ISSMResource *> *pList) = 0;
+ virtual SSMRESULT getList(std::vector<ISSMResource *> *pList) = 0;
};
class IResourceFinderEvent
virtual SSMRESULT stopObserveResource(IN ISSMResource *pSensor) = 0;
};
-static const OID OID_IResourceConnectivity = { 0x8e42b098, 0x9aa5, 0x43f3, { 0x84, 0xa, 0x21, 0x44, 0xc9, 0x4c, 0xc7, 0x99 } };
-class IResourceConnectivity : public IBase
-{
- public:
- virtual void *getPlatform() = 0;
-};
-
/**
* @class ISoftSensorManager
* @brief ISoftSensorManager Interface
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics 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.
+*
+******************************************************************/
#include "ThreadManager.h"
CSimpleMutex::CSimpleMutex()
SSM_CLEANUP_ASSERT(m_pContextRepository->registerResourceFinderEvent(this));
- SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
+ SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
SSM_CLEANUP_ASSERT(initializeEngine());
std::vector<ISSMResource *> contextModelList;
std::stringstream sstream;
- m_pResponseReactor->getList(&contextModelList);
+ m_pSensingEngine->getList(&contextModelList);
for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
itor != contextModelList.end(); ++itor)
{
return res;
}
-SSMRESULT CPropagationEngine::installResponseReactor(IN IResponseReactor *pResponseReactor)
+SSMRESULT CPropagationEngine::installCurrentSensors()
{
SSMRESULT res = SSM_E_FAIL;
std::vector<ISSMResource *> contextModelList;
- pResponseReactor->getList(&contextModelList);
+ m_pSensingEngine->getList(&contextModelList);
for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
itor != contextModelList.end(); ++itor)
SSM_CLEANUP_ASSERT(updateDeviceInfo(&ssmResource, NULL));
- SSM_CLEANUP_ASSERT(installResponseReactor(m_pResponseReactor));
+ SSM_CLEANUP_ASSERT(installCurrentSensors());
CLEANUP:
SAFE_RELEASE(pRootModel);
{
case IContextModel::STATUS_ACTIVATE:
pModel->addRef();
- m_pResponseReactor->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+ m_pSensingEngine->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
break;
case IContextModel::STATUS_DEACTIVATE:
- m_pResponseReactor->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+ m_pSensingEngine->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
//pModel->CleanUpModelData();
pModel->release();
break;
case IContextModel::STATUS_START_READ_VALUE:
//Model must be released from OnEvent callType
pModel->addRef();
- m_pResponseReactor->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
+ m_pSensingEngine->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
break;
case IContextModel::STATUS_STOP_READ_VALUE:
CSimpleMutex m_mtxContextModelList;
CSimpleMutex m_mtxLookUpList;
- CObjectPtr<IResponseReactor> m_pResponseReactor;
+ CObjectPtr<ISensingEngine> m_pSensingEngine;
CObjectPtr<IContextModel> m_pDeviceModel;
SSMRESULT addResourceFromGetList();
//TODO: Install Context model from SSMResource
- SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
+ SSMRESULT installCurrentSensors();
- SSMRESULT installResponseReactor(IN IResponseReactor *pResponseReactor);
+ SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
SSMRESULT installContextModel(IN IContextModel *pParentModel,
IN IContextModel::ConstructionType constructionType,
#ifndef _SSMCore_H_
#define _SSMCore_H_
-#include <string>
-#include <vector>
-
+#include "SSMInterface.h"
#include "SSMModelDefinition.h"
#define IN
*/
#define INTERFACE_DECLSPEC
-enum SSMRESULT
-{
- SSM_S_OK
- , SSM_S_FALSE
- , SSM_E_POINTER
- , SSM_E_OUTOFMEMORY
- , SSM_E_FAIL
- , SSM_E_NOINTERFACE
- , SSM_E_NOTIMPL
-};
-
-/**
-* @class IModelData
-* @brief IModelData Interface
-* This class represents context model data package
-*
-* @see
-*/
-class IModelData
-{
- public:
- /**
- * @fn getDataId
- * @brief Get affected DataId. ContextModel has plenty of data so \n
- * returned data is matched from given condition
- *
- * @param None
- *
- * @return int
- * @warning
- * @exception
- * @see
- */
- virtual int getDataId() = 0;
-
- /**
- * @fn GetPropertyCount
- * @brief ContextModel has at least one property that contains data \n
- * property is described from its specification.
- *
- * @param None
- *
- * @return int
- * @warning
- * @exception
- * @see
- */
- virtual int getPropertyCount() = 0;
-
- /**
- * @fn getPropertyName
- * @brief Retrieve propertyName
- *
- * @param [in] int propertyIndex - index of property to read
- *
- * @return std::string
- * @warning
- * @exception
- * @see
- */
- virtual std::string getPropertyName(IN int propertyIndex) = 0;
-
- /**
- * @fn getPropertyValue
- * @brief Retrieve propertyValue
- *
- * @param [in] int propertyIndex - index of property to read
- *
- * @return std::string
- * @warning
- * @exception
- * @see
- */
- virtual std::string getPropertyValue(IN int propertyIndex) = 0;
-
- /**
- * @fn getPropertyValueByName
- * @brief Retrieve propertyValue using given name
- *
- * @param [in] std::string propertyName - property name looking for
- *
- * @return std::string
- * @warning
- * @exception
- * @see
- */
- virtual std::string getPropertyValueByName(IN std::string propertyName) = 0;
- protected:
- virtual ~IModelData() {};
-};
-
-/**
-* @class IDataReader
-* @brief IDataReader Interface
-* This class represents context model data package's reader
-*
-* @see
-*/
-class IDataReader
-{
- public:
- /**
- * @fn getAffectedModels
- * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
- *
- * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT getAffectedModels(OUT std::vector<std::string> *pAffectedModels) = 0;
-
- /**
- * @fn getModelDataCount
- * @brief Get affected data count. There are multiple data can exist from given condition.
- *
- * @param [in] std::string modelName - affected ContextModel name
- *
- * @param [out] int *pDataCount - affected dataId count
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT getModelDataCount(IN std::string modelName, OUT int *pDataCount) = 0;
-
- /**
- * @fn getModelData
- * @brief Get actual Context Model data
- *
- * @param [in] std::string modelName - affected ContextModel name
- *
- *
- * @param [in] int dataIndex - affected dataId index
- *
- *
- * @param [out] IModelData **ppModelData - affected ContextModel data reader
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT getModelData(IN std::string modelName, IN int dataIndex,
- OUT IModelData **ppModelData) = 0;
- protected:
- virtual ~IDataReader() {};
-};
-
-/**
-* @class IQueryEngineEvent
-* @brief IQueryEngineEvent Interface
-* This class represents Query Engine's event that contains results
-*
-* @see
-*/
-class IQueryEngineEvent
-{
- public:
- /**
- * @fn onQueryEngineEvent
- * @brief Transmit result of SSMCore to Application layer
- *
- * @param [in] int cqid - entered ContextQuery ID
- *
- * @param [in] IDataReader *pResult - result of SSMCore
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult) = 0;
- protected:
- virtual ~IQueryEngineEvent() {};
-};
-
/**
* @class IQueryEngine
* @brief IQueryEngine Interface
* limitations under the License.
*
******************************************************************/
+#include "SSMCore.h"
#include "SSMInterface/SSMCore_JNI.h"
#include "Common/PlatformLayer.h"
#define _SSMCore_JNI_H_
#include <jni.h>
-#include "SSMCore.h"
#ifdef __cplusplus
extern "C" {
std::stringstream sstream;
// QueryEngine Id
- queryEventResult["queryEngineId"].push_back(m_queryEngineId);
+ queryEventResult["queryEngineId"] = m_queryEngineId;
// CQID
sstream << cqid;
- queryEventResult["CQID"].push_back(sstream.str());
+ queryEventResult["CQID"] = sstream.str();
sstream.str("");
pResult->getAffectedModels(&affectedModels);
// Affected Model Count
sstream << affectedModels.size();
- queryEventResult["modelCount"].push_back(sstream.str());
+ queryEventResult["modelCount"] = sstream.str();
sstream.str("");
//TODO: we assume that contains only one model at time
{
// Model Name
sstream << (*itor);
- queryEventResult["modelName"].push_back(sstream.str());
+ queryEventResult["modelName"] = sstream.str();
sstream.str("");
pResult->getModelDataCount(*itor, &dataCount);
// Data Count
sstream << dataCount;
- queryEventResult["dataCount"].push_back(sstream.str());
+ queryEventResult["dataCount"] = sstream.str();
sstream.str("");
//FixME: we have to support multiple data count
// Data Id
sstream << pModelData->getDataId();
- queryEventResult["dataId"].push_back(sstream.str());
+ queryEventResult["dataId"] = sstream.str();
sstream.str("");
// Property Count
sstream << pModelData->getPropertyCount();
- queryEventResult["propertyCount"].push_back(sstream.str());
+ queryEventResult["propertyCount"] = sstream.str();
sstream.str("");
for (int j = 0; j < pModelData->getPropertyCount(); j++)
{
// Property Name & Value
sstream << pModelData->getPropertyValue(j).c_str();
- queryEventResult[pModelData->getPropertyName(j).c_str()].push_back(sstream.str());
+ queryEventResult[pModelData->getPropertyName(j).c_str()] = sstream.str();
sstream.str("");
}
}
}
g_vecQueryEventResults.push_back(queryEventResult);
- OCPlatform::notifyObservers(m_hSSMResource);
+
+ //TODO: need to modify for notifying proper clients
+ OCPlatform::notifyAllObservers(m_hSSMResource);
return SSM_S_OK;
}
SSMResourceServer::SSMResourceServer()
{
- m_pPlatform = NULL;
m_hSSMResource = NULL;
}
int SSMResourceServer::initializeManager(std::string &xmlDescription)
{
SSMRESULT res = SSM_E_FAIL;
- CObjectPtr < IResourceConnectivity > pResourceConnectivity;
SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
SSM_CLEANUP_ASSERT(StartSSMCore());
- SSM_CLEANUP_ASSERT(
- CreateGlobalInstance(OID_IResourceConnectivity, (IBase **) &pResourceConnectivity));
-
- m_pPlatform = (OC::OCPlatform *) pResourceConnectivity->getPlatform();
-
if (createResource() != 0)
{
SSM_CLEANUP_ASSERT (SSM_E_FAIL);
int SSMResourceServer::createResource()
{
std::string resourceURI = "/service/SoftSensorManager"; // URI of the resource
- std::string resourceTypeName =
- "core.SoftSensorManager"; // resource type name. In this case, it is light
+ std::string resourceTypeName = "core.SoftSensorManager"; // resource type name.
std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
// This will internally create and register the resource.
- OCStackResult result = m_pPlatform->registerResource(m_hSSMResource, resourceURI,
+ OCStackResult result = OCPlatform::registerResource(m_hSSMResource, resourceURI,
resourceTypeName, resourceInterface,
std::bind(&SSMResourceServer::entityHandler, this, std::placeholders::_1,
std::placeholders::_2), resourceProperty);
return 0;
}
-void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request,
+ std::shared_ptr< OCResourceResponse > response)
{
SSMRESULT res = SSM_E_FAIL;
{
// Get the request type and request flag
std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+ int requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == RequestHandlerFlag::InitFlag)
+ if (requestFlag & RequestHandlerFlag::InitFlag)
{
// entity handler to perform resource initialization operations
}
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
{
+ cout << "\t\trequestFlag : Request\n";
+
// If the request type is GET
if (requestType == "GET")
{
AttributeMap responseAttributeMap;
// Process query params and do required operations ..
- if (requestAttributeMap["command"].back() == "CreateQueryEngine")
+ if (requestAttributeMap["command"] == "CreateQueryEngine")
{
CQueryEngineEvent *queryEngineEvent = NULL;
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("CreateQueryEngine failed");
+ responseAttributeMap["error"] = "CreateQueryEngine failed";
goto CLEANUP;
}
if (queryEngineEvent == NULL)
{
- responseAttributeMap["error"].push_back(
- "QueryEngineEvent create failed");
+ responseAttributeMap["error"] =
+ "QueryEngineEvent create failed";
goto CLEANUP;
}
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("RegisterQueryEvent failed");
+ responseAttributeMap["error"] = "RegisterQueryEvent failed";
goto CLEANUP;
}
- responseAttributeMap["queryEngineId"].push_back(sstream.str());
+ responseAttributeMap["queryEngineId"] = sstream.str();
}
- else if (requestAttributeMap["command"].back() == "ReleaseQueryEngine")
+ else if (requestAttributeMap["command"] == "ReleaseQueryEngine")
{
- pQueryEngine = (IQueryEngine *) stoi(
- requestAttributeMap["queryEngineId"].back());
+ pQueryEngine = (IQueryEngine *) std::stoi(
+ requestAttributeMap["queryEngineId"]);
ReleaseQueryEngine(pQueryEngine);
}
- else if (requestAttributeMap["command"].back() == "ExecuteContextQuery")
+ else if (requestAttributeMap["command"] == "ExecuteContextQuery")
{
int CQID = 0;
- pQueryEngine = (IQueryEngine *) stoi(
- requestAttributeMap["queryEngineId"].back());
+ pQueryEngine = (IQueryEngine *) std::stoi(
+ requestAttributeMap["queryEngineId"]);
res = pQueryEngine->executeContextQuery(
- requestAttributeMap["contextQuery"].back(), &CQID);
+ requestAttributeMap["contextQuery"], &CQID);
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("ExecuteContextQuery failed");
+ responseAttributeMap["error"] = "ExecuteContextQuery failed";
goto CLEANUP;
}
sstream << CQID;
- responseAttributeMap["CQID"].push_back(sstream.str());
+ responseAttributeMap["CQID"] = sstream.str();
}
- else if (requestAttributeMap["command"].back() == "KillContextQuery")
+ else if (requestAttributeMap["command"] == "KillContextQuery")
{
- pQueryEngine = (IQueryEngine *) stoi(
- requestAttributeMap["queryEngineId"].back());
+ pQueryEngine = (IQueryEngine *) std::stoi(
+ requestAttributeMap["queryEngineId"]);
- res = pQueryEngine->killContextQuery(stoi(requestAttributeMap["CQID"].back()));
+ res = pQueryEngine->killContextQuery(std::stoi(requestAttributeMap["CQID"]));
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("KillContextQuery failed");
+ responseAttributeMap["error"] = "KillContextQuery failed";
goto CLEANUP;
}
}
// DELETE request operations
}
}
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
{
// perform observe related operations on the resource.
}
}
- else
- {
- }
+
+ return OC_EH_OK;
}
int initializeManager(std::string &xmlDescription);
int terminateManager();
- void entityHandler(std::shared_ptr< OC::OCResourceRequest > request,
- std::shared_ptr< OC::OCResourceResponse > response);
+ OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest > request,
+ std::shared_ptr< OC::OCResourceResponse > response);
private:
- OC::OCPlatform *m_pPlatform;
OCResourceHandle m_hSSMResource;
int createResource();
};
#include "QueryProcessor/ConditionedModel.h"
#include "QueryProcessor/EvaluationEngine.h"
#include "QueryProcessor/PropagationEngine.h"
-#include "SensorProcessor/ResponseReactor.h"
+#include "SensorProcessor/SensingEngine.h"
#include "SensorProcessor/ContextExecutor.h"
#include "SensorProcessor/ContextDataReader.h"
#include "SensorProcessor/ResourceFinder.h"
-#include "SensorProcessor/ResourceConnectivity.h"
inline bool operator<( const OID &lhs, const OID &rhs )
{
}
SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IContextRepository, (IBase **)&m_pContextRepository));
- SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
- m_pContextRepository->setCurrentDeviceInfo(name, type, pathSoftSensors, pathDescription);
+ SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
+ SSM_CLEANUP_ASSERT(m_pContextRepository->initRepository(name, type, pathSoftSensors,
+ pathDescription));
SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IPropagationEngine, (IBase **)&m_pPropagationEngine));
SSMRESULT CSoftSensorManager::getInstalledModelList(OUT std::vector<ISSMResource *> *pList)
{
- m_pResponseReactor->getList(pList);
+ m_pSensingEngine->getList(pList);
return SSM_S_OK;
}
SSM_CLEANUP_ASSERT(CreateInstance(OID_IContextDataReader, ppvObject));
}
}
- else if (IsEqualOID(OID_IResponseReactor, objectID))
+ else if (IsEqualOID(OID_ISensingEngine, objectID))
{
- if (g_globalInstance->find(OID_IResponseReactor) == g_globalInstance->end())
+ if (g_globalInstance->find(OID_ISensingEngine) == g_globalInstance->end())
{
- SSM_CLEANUP_ASSERT(CreateInstance(OID_IResponseReactor, ppvObject));
- }
- }
- else if (IsEqualOID(OID_IResourceConnectivity, objectID))
- {
- if (g_globalInstance->find(OID_IResourceConnectivity) == g_globalInstance->end())
- {
- SSM_CLEANUP_ASSERT(CreateInstance(OID_IResourceConnectivity, ppvObject));
+ SSM_CLEANUP_ASSERT(CreateInstance(OID_ISensingEngine, ppvObject));
}
}
else
{
SSM_CLEANUP_ASSERT(CreateNewObject<CContextRepository>(objectID, ppObject));
}
- else if (IsEqualOID(OID_IResponseReactor, objectID))
+ else if (IsEqualOID(OID_ISensingEngine, objectID))
{
- SSM_CLEANUP_ASSERT(CreateNewObject<CResponseReactor>(objectID, ppObject));
+ SSM_CLEANUP_ASSERT(CreateNewObject<CSensingEngine>(objectID, ppObject));
}
else if (IsEqualOID(OID_IContextExecutor, objectID))
{
{
SSM_CLEANUP_ASSERT(CreateNewObject<CContextDataReader>(objectID, ppObject));
}
- else if (IsEqualOID(OID_IResourceConnectivity, objectID))
- {
- SSM_CLEANUP_ASSERT(CreateNewObject<CResourceConnectivity>(objectID, ppObject));
- }
CLEANUP:
return res;
private:
CObjectPtr<IContextRepository> m_pContextRepository;
CObjectPtr<IPropagationEngine> m_pPropagationEngine;
- CObjectPtr<IResponseReactor> m_pResponseReactor;
+ CObjectPtr<ISensingEngine> m_pSensingEngine;
public:
SSMRESULT finalConstruct();
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics 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.
- *
- ******************************************************************/
-
-/*
- * SSMResourceServerLauncher.cpp
- */
-#include "SSMResourceServer.h"
-
-string xmlDescription = "<SSMCore>"
- "<Device>"
- "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
- "<Name>MyPC</Name>"
- "<Type>PC</Type>"
- "</Device>"
- "</SSMCore>";
-
-using namespace std;
-
-int main(int argc, char *argv[])
-{
- int inputKey = 0;
-
- try
- {
- SSMResourceServer ssmResourceServer;
-
- cout << "Initializing Resource Server" << endl;
-
- if (ssmResourceServer.initializeManager(xmlDescription) != 0)
- {
- cout << "SSM Resource Server init failed" << endl;
- return -1;
- }
-
- cout << "SSM Resource Server is working, press anykey to terminate" << endl;
-
- cin >> inputKey;
-
- cout << "SSM Resource Server is terminating" << endl;
-
- if (ssmResourceServer.terminateManager() != 0)
- {
- cout << "SSM Resource Server terminate failed" << endl;
- }
- }
- catch (std::exception e)
- {
- cout << e.what() << endl;
- }
-
- cout << "bye bye" << endl;
-}
m_pContextDataReader->getContextData(modelName, startIndex, count, data, pLastIndex);
}
-std::string CContextExecutor::checkError(std::vector<ContextData> data)
-{
- std::string errorMsg = "OK";
-
- for (unsigned int i = 0 ; i < data.size() ; ++i)
- {
- if (data[i].outputProperty[0].find("error") != data[i].outputProperty[0].end())
- {
- errorMsg = data[i].outputProperty[0].find("error")->second ;
- break;
- }
- }
-
- return errorMsg;
-}
-
void CContextExecutor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
IEvent *pEvent)
{
std::string primitiveSensor)
{
//check m_relatedSoftSensor / apply timestamp
- std::map<std::string, std::vector<ContextData> > returnData;
SSMRESULT ret = SSM_E_FAIL;
+ std::map<std::string, std::vector<ContextData> > returnData;
+ std::vector<ContextData> contextDataList;
+
for (unsigned int i = 0; i < m_relatedSoftSensor[primitiveSensor].size(); ++i)
{
std::string softSensorName = m_relatedSoftSensor[primitiveSensor][i];
{
ret = SSM_S_OK;
std::vector<std::string> inputList = m_registeredResources[softSensorName]->inputList;
- std::vector<ContextData> contextDataList;
for (unsigned int j = 0; j < inputList.size(); j++) //check all "inputlist" arrived or not
{
if (m_storedPrimitiveSensorData.find(inputList[j]) == m_storedPrimitiveSensorData.end())
{
+ //Still we have partial data
ret = SSM_E_FAIL;
break;
}
else
{
- std::vector<ContextData> primitiveSensorData = m_storedPrimitiveSensorData[inputList[j]];
- for (unsigned k = 0; k < primitiveSensorData.size(); k++)
+ //Copy all properties of current primitiveSensor data to outputs
+ for (std::vector<ContextData>::iterator itor = m_storedPrimitiveSensorData[inputList[j]].begin();
+ itor != m_storedPrimitiveSensorData[inputList[j]].end(); ++itor)
{
- contextDataList.push_back(primitiveSensorData[k]);
+ contextDataList.push_back(*itor);
}
}
}
+ //We have all inputs
if (ret == SSM_S_OK)
{
returnData.insert(std::make_pair(softSensorName, contextDataList));
//find soft sensor
std::map<std::string, std::vector<ContextData> > readyContextList = getPreparedContextList(type);
- if (readyContextList.size() > 0)
+ //Run SoftSensor! readyContextList has all data for run
+ std::map<std::string, std::vector<ContextData> >::iterator iter;
+ for (iter = readyContextList.begin(); iter != readyContextList.end(); ++iter)
{
- //Run SoftSensor! readyContextList has all data for run
- std::map<std::string, std::vector<ContextData> >::iterator iter = readyContextList.begin();
- for (; iter != readyContextList.end(); ++iter)
- {
- std::string softSensorName = iter->first;
- std::vector<ContextData> inputData = iter->second;
- std::string errorMsg = checkError(inputData);
+ std::string softSensorName = iter->first;
+ std::vector<ContextData> inputData = iter->second;
- if (!errorMsg.compare("OK"))
- {
- runLogic(inputData, softSensorName);
- }
- else
- {
- inputData.clear();
- inputData.push_back(makeErrorContextData(softSensorName, errorMsg));
- addOutput(inputData);
- }
- }
+ runLogic(inputData, softSensorName);
}
}
else //This data is primitive
m_ctxEventList[softSensor]->onCtxEvent(SPF_START, inputData);
}
m_mtxLibraryIO.unlock();
-}
-
-ContextData CContextExecutor::makeErrorContextData(std::string rootName, std::string errMsg)
-{
- std::map<std::string, std::string> errorMap;
- ContextData errorContextData;
-
- errorMap.insert(std::make_pair("error", errMsg));
- errorMap.insert(std::make_pair("available", "false"));
- errorContextData.rootName = rootName;
- errorContextData.outputPropertyCount = 2;
- errorContextData.outputProperty.push_back(errorMap);
-
- return errorContextData;
}
\ No newline at end of file
std::map<std::string, std::vector<ContextData> > getPreparedContextList(
IN std::string primitiveSensor);
void runLogic(IN std::vector<ContextData> inputData, IN std::string softSensor);
- ContextData makeErrorContextData(IN std::string rootName, IN std::string errMsg);
- std::string checkError(IN std::vector<ContextData> data);
-
};
#endif
{
}
-void CContextRepository::setCurrentDeviceInfo(IN std::string name, IN std::string type,
+SSMRESULT CContextRepository::initRepository(IN std::string name, IN std::string type,
IN std::string pathSoftSensors, IN std::string pathDescription)
{
- //TODO: Someone need to provides a way to generate permanent uuid function
- /*
- m_currentDeviceInfo.friendlyName = name;
- //m_currentDeviceInfo.ID="2fac1234-31f8-11b4-a222-08002b34c003";
- m_currentDeviceInfo.ID = udn;
- m_currentDeviceInfo.IPAddress = "127.0.0.1";
- m_currentDeviceInfo.tp = tp;
- //m_currentDeviceInfo.type = SSM_DEVICE_MOBILE;
- m_currentDeviceInfo.type = td;
- */
+ SSMRESULT res = SSM_E_FAIL;
+
+ std::vector<DictionaryData> dict;
+
m_name = name;
m_type = type;
- m_pathSoftSensors = pathSoftSensors;
- m_pathSoftSensorsDescription = pathDescription;
+
+ if (pathSoftSensors.length() == 0)
+ {
+ SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
+ m_pathSoftSensors.append("/");
+ }
+ else
+ {
+ m_pathSoftSensors = pathSoftSensors;
+ }
+
+ if (pathDescription.length() == 0)
+ {
+ SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensorsDescription));
+ m_pathSoftSensorsDescription.append("/");
+ m_pathSoftSensorsDescription.append(DEFAULT_PATH_SOFT_SENSORS);
+ }
+ else
+ {
+ m_pathSoftSensorsDescription = pathDescription;
+ }
+
+
+ SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
+ SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, &m_lstSoftSensor));
+
+CLEANUP:
+ return res;
}
SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
keyStr = subItem->name(); // key
valueStr = subItem->value(); // value
- if (!keyStr.compare("root_name"))
+ if (!keyStr.compare("name"))
{
dictionaryData.rootName = trim_both(valueStr);
}
keyStr = subItem2->name(); // key
valueStr = subItem2->value(); // value
- if (!keyStr.compare("attribute_property_count"))
- {
- dictionaryData.attributePropertyCount = trim_both(valueStr);
- }
- else if (!keyStr.compare("output_property_count"))
- {
- dictionaryData.outputPropertyCount = trim_both(valueStr);
- }
- if (!keyStr.compare("inputs_count"))
- {
- dictionaryData.inputCount = trim_both(valueStr);
- }
- else if (!keyStr.compare("app_inputs_count"))
- {
- dictionaryData.appInputCount = trim_both(valueStr);
- }
- else if (!keyStr.compare("app_input"))
- {
- dictionaryData.appInputs.push_back(trim_both(valueStr));
- }
- else if (!keyStr.compare("input"))
+ if (!keyStr.compare("input"))
{
dictionaryData.inputs.push_back(trim_both(valueStr));
}
////std::cout<<name << " :: " << subItem2->value() <<std::endl<<std::endl;
for (subItem3 = subItem2->first_node(); subItem3 ; subItem3 = subItem3->next_sibling())
{
-
std::string newKeyStr = subItem3->name(); // key
valueStr = subItem3->value(); // value
- if (!keyStr.compare("attribute_property") || !keyStr.compare("output_property") )
- {
- propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr))) ;
- }
- else if (!keyStr.compare("enter_condition"))
+ if (!keyStr.compare("attribute") || !keyStr.compare("output") )
{
- enterconditionVector.push_back(trim_both(valueStr));
+ propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr)));
}
}
- if (!keyStr.compare("attribute_property"))
+ if (!keyStr.compare("attribute"))
{
dictionaryData.attributeProperty.push_back(propertyMap);
}
- else if (!keyStr.compare("output_property"))
+ else if (!keyStr.compare("output"))
{
dictionaryData.outputProperty.push_back(propertyMap);
}
- else if (!keyStr.compare("enter_condition"))
- {
- dictionaryData.enterConditions.push_back(enterconditionVector);
- }
}
}
//for accurate data.
SSMRESULT res = SSM_E_FAIL;
std::basic_ifstream< char > xmlFile(descriptionFilePath.c_str());
- if (descriptionFilePath.length() > 0 && xmlFile.fail())
- {
- //error while opening given path, return error
- SSM_CLEANUP_ASSERT(SSM_E_FAIL);
- }
-
- if (descriptionFilePath.length() == 0)
- {
- //No given path, try to open local Path
- std::string path;
- SSM_CLEANUP_ASSERT(GetCurrentPath(&path));
- path.append("/");
- path.append(DEFAULT_PATH_SOFT_SENSORS);
- xmlFile.open(path);
- }
-
//path loaded
if (!xmlFile.fail())
{
SSMRESULT CContextRepository::getSoftSensorList(OUT std::vector<ISSMResource *> *pSoftSensorList)
{
- SSMRESULT res = SSM_E_FAIL;
- std::vector<DictionaryData> dict;
-
- SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
-
- SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, pSoftSensorList));
+ for (size_t i = 0; i < m_lstSoftSensor.size(); i++)
+ {
+ pSoftSensorList->push_back(m_lstSoftSensor.at(i));
+ }
-CLEANUP:
- return res;
+ return SSM_S_OK;
}
SSMRESULT CContextRepository::getPrimitiveSensorList(OUT std::vector<ISSMResource *>
*pPrimitiveSensorList)
{
- for (size_t i = 0; i < m_lstSensor.size(); i++)
+ for (size_t i = 0; i < m_lstPrimitiveSensor.size(); i++)
{
- pPrimitiveSensorList->push_back(m_lstSensor.at(i));
+ pPrimitiveSensorList->push_back(m_lstPrimitiveSensor.at(i));
}
return SSM_S_OK;
SSMRESULT CContextRepository::onResourceFound(IN ISSMResource *pSensor)
{
- m_lstSensor.push_back(pSensor);
+ m_lstPrimitiveSensor.push_back(pSensor);
for (size_t i = 0; i < m_resourceEvents.size(); i++)
{
SSMRESULT CContextRepository::onResourceLost(IN ISSMResource *pSensor)
{
std::vector<ISSMResource *>::iterator itor;
- itor = std::find(m_lstSensor.begin(), m_lstSensor.end(), pSensor);
+ itor = std::find(m_lstPrimitiveSensor.begin(), m_lstPrimitiveSensor.end(), pSensor);
- if (itor != m_lstSensor.end())
+ if (itor != m_lstPrimitiveSensor.end())
{
- m_lstSensor.erase(itor);
+ m_lstPrimitiveSensor.erase(itor);
return SSM_S_OK;
}
typedef void(*InitContext)(IN ICtxDelegate *);
InitContext InitializeContextFunction = NULL;
- if (m_pathSoftSensors.length() == 0)
- {
- SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
- }
-
- m_pathSoftSensors.append("/");
-
// load dll(so)
res = SSM_E_FAIL;
for (unsigned int i = 1; i <= SSM_MODEL_RETRY; ++i)
{
InitializeContextFunction = (InitContext)GetProcAddress(hModule, "InitializeContext");
}
-#else
- //sstream << "/data/data/com.example.javaproject/lib/lib" << modelName <<".so" << std::ends;
+#elif defined(LINUX)
sstream << m_pathSoftSensors << "lib" << softSensorName.c_str() << ".so" << std::ends;
void *hModule = NULL;
#endif
if (hModule == NULL)
{
- InitializeContextFunction = NULL;
- continue;
+ //load library failed. raise error
+ SSM_CLEANUP_ASSERT(SSM_E_FAIL);
+ //InitializeContextFunction = NULL;
+ //continue;
}
if (InitializeContextFunction != NULL)
{
private:
CSimpleMutex m_mtxFileIO;
- std::vector<ISSMResource *> m_lstSensor;
+ std::vector<ISSMResource *> m_lstPrimitiveSensor;
+ std::vector<ISSMResource *> m_lstSoftSensor;
CObjectPtr<IResourceFinder> m_resourceFinder;
std::string m_name;
std::string m_type;
/**
- * @fn setCurrentDeviceInfo
- * @brief set device information
+ * @fn initRepository
+ * @brief initialize repository using given info
*
* @param [in] std::string name - Device name
* @param [in] std::string type - Device Type
* @param [in] std::string pathSoftSensors - SoftSensors Repository path
* @param [in] std::string pathDescription - SoftSensors Description path
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- void setCurrentDeviceInfo(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
- IN std::string pathDescription);
+ SSMRESULT initRepository(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
+ IN std::string pathDescription);
/**
* @fn getSoftSensorList
+++ /dev/null
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics 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.
-*
-******************************************************************/
-#include "ResourceConnectivity.h"
-
-SSMRESULT CResourceConnectivity::finalConstruct()
-{
- SSMRESULT res = SSM_E_FAIL;
- OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
- "134.134.161.33", 56831, OC::QualityOfService::NonConfirmable);
-
- m_pPlatform = new OC::OCPlatform(cfg);
-
- SSM_CLEANUP_NULL_ASSERT(m_pPlatform);
-
- res = SSM_S_OK;
-
-CLEANUP:
- return res;
-}
-
-void CResourceConnectivity::finalRelease()
-{
- SAFE_DELETE(m_pPlatform);
-}
-
-void *CResourceConnectivity::getPlatform()
-{
- return m_pPlatform;
-}
+++ /dev/null
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics 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.
-*
-******************************************************************/
-#ifndef _ResourceConnectivity_H_
-#define _ResourceConnectivity_H_
-
-#include "SSMInterface/SSMCore.h"
-#include "Common/PlatformLayer.h"
-#include "Common/InternalInterface.h"
-#include "OCPlatform.h"
-
-class CResourceConnectivity :
- public CObjectRoot<CObjectMultiThreadModel>
- , public IResourceConnectivity
-{
- public:
- SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
- {
- if (ppObject == NULL)
- return SSM_E_POINTER;
-
- if (IsEqualOID(objectID, OID_IResourceConnectivity))
- {
- IBase *pBase = (IResourceConnectivity *)this;
- pBase->addRef();
- *ppObject = pBase;
- return SSM_S_OK;
- }
-
- return SSM_E_NOINTERFACE;
- }
-
- SSMRESULT finalConstruct();
- void finalRelease();
-
- void *getPlatform();
-
- private:
- OC::OCPlatform *m_pPlatform;
-};
-
-#endif
{
SSMRESULT res = SSM_E_FAIL;
+ OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+ "0.0.0.0", 0, OC::QualityOfService::LowQos);
+
SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ITasker, (IBase **)&m_pTasker));
- SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResourceConnectivity,
- (IBase **)&m_pResourceConnectivity));
+
+ OC::OCPlatform::Configure(cfg);
m_pResourceFinderEvent = NULL;
- m_pPlatform = (OC::OCPlatform *)m_pResourceConnectivity->getPlatform();
CLEANUP:
return res;
pMessage[0] = RESOURCE_DISCOVER_REQUESTPROFILE;
pMessage[1] = (int)new std::shared_ptr<OC::OCResource>(resource);
+ std::string path = resource->host() + resource->uri();
+
m_pTasker->addTask(this, pMessage);
}
}
SSMRESULT CResourceFinder::startResourceFinder()
{
- //m_pPlatform->findResource("", "oc/core/service/SoftSensorManager/SoftSensor",
- m_pPlatform->findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
- std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+ OCStackResult res = OC_STACK_ERROR;
+
+ res = OC::OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
+ std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+
+ if (res != OC_STACK_OK)
+ return SSM_E_FAIL;
return SSM_S_OK;
}
SSM_CLEANUP_ASSERT(pResourceHandler->initHandler(*pResource, this));
m_mapResourceHandler[pResource->get()->host() + pResource->get()->uri()] = pResourceHandler;
pResource->get()->get(queryParams, std::bind(&OICResourceHandler::onGetResourceProfile,
- pResourceHandler, std::placeholders::_1, std::placeholders::_2));
+ pResourceHandler, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
break;
case RESOURCE_DISCOVER_SETUP_RESOURCE:
#include "Common/PlatformLayer.h"
#include "Common/InternalInterface.h"
#include "OCPlatform.h"
+#include "OCApi.h"
class CResourceFinder :
public CObjectRoot<CObjectMultiThreadModel>
m_pResource.get()->observe(OC::ObserveType::Observe, queryParams,
std::bind(&OICResourceHandler::onResourceDataReceived,
- this, std::placeholders::_1, std::placeholders::_2));
+ this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
return SSM_S_OK;
}
return SSM_S_OK;
}
- void onResourceDataReceived(const OC::OCRepresentation &representation, const int &eCode)
+ void onResourceDataReceived(const OC::HeaderOptions headerOptions,
+ const OC::OCRepresentation &representation,
+ const int &eCode, const int &sequenceNumber)
{
if (eCode == 0)
{
{
for (size_t i = 0; i < attributeMap.size() / 3; i++)
{
- outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
- outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
- outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+ outputProperty["name"] = attributeMap.find(toString(i * 3))->second;
+ outputProperty["type"] = attributeMap.find(toString(i * 3 + 1))->second;
+ outputProperty["value"] = attributeMap.find(toString(i * 3 + 2))->second;
ctxData.outputProperty.push_back(outputProperty);
}
}
}
- void onGetResourceProfile(const OC::OCRepresentation &representation, const int &eCode)
+ void onGetResourceProfile(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &representation, const int &eCode)
{
//unpack attributeMap
//TODO: Temporally used for json parsing limitation
for (size_t i = 0; i < attributeMap.size() / 3; i++)
{
- outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
- outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
- outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+ outputProperty["name"] = attributeMap.find(toString(i * 3))->second;
+ outputProperty["type"] = attributeMap.find(toString(i * 3 + 1))->second;
+ outputProperty["value"] = attributeMap.find(toString(i * 3 + 2))->second;
pSSMResource->outputProperty.push_back(outputProperty);
}
/////////////////////////////////////////////////////
std::shared_ptr<OC::OCResource> m_pResource;
IThreadClient *m_pResourceFinderClient;
IEvent *m_pEvent;
+
+ std::string toString(int t)
+ {
+ std::ostringstream os;
+ os << t;
+ return os.str();
+ }
};
enum RESOURCE_DISCOVER_STATE {RESOURCE_DISCOVER_REQUESTPROFILE, RESOURCE_DISCOVER_SETUP_RESOURCE};
- OC::OCPlatform *m_pPlatform;
- CObjectPtr<IResourceConnectivity> m_pResourceConnectivity;
IResourceFinderEvent *m_pResourceFinderEvent;
CObjectPtr<ITasker> m_pTasker;
std::map<std::string , OICResourceHandler *> m_mapResourceHandler;
* limitations under the License.
*
******************************************************************/
-#include "ResponseReactor.h"
+#include "SensingEngine.h"
-SSMRESULT CResponseReactor::finalConstruct()
+SSMRESULT CSensingEngine::finalConstruct()
{
SSMRESULT res = SSM_S_OK;
return res;
}
-void CResponseReactor::finalRelease()
+void CSensingEngine::finalRelease()
{
}
-void CResponseReactor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
- IEvent *pEvent)
+SSMRESULT CSensingEngine::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
+ IEvent *pEvent)
{
m_mtxRequestedContextData.lock();
// if already exists
m_pContextExecutor->registerContext(callType, pSSMResource, this);
m_mtxRequestedContextData.unlock();
+
+ return SSM_S_OK;
}
-void CResponseReactor::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+SSMRESULT CSensingEngine::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
IEvent *pEvent)
{
m_mtxUnregisterContext.lock();
}
m_mtxUnregisterContext.unlock();
+
+ return SSM_S_OK;
}
-void CResponseReactor::getList(std::vector<ISSMResource *> *pList)
+SSMRESULT CSensingEngine::getList(std::vector<ISSMResource *> *pList)
{
pList->clear();
m_pContextRepository->getSoftSensorList(pList);
m_pContextRepository->getPrimitiveSensorList(pList);
+
+ return SSM_S_OK;
}
//Dispatch to upper layer
-int CResponseReactor::onEvent(std::string type, TypeofEvent callType,
- std::vector<ContextData> ctxData)
+int CSensingEngine::onEvent(std::string type, TypeofEvent callType,
+ std::vector<ContextData> ctxData)
{
std::map<std::string, CallbackData >::iterator itor;
#include "SSMInterface/SSMCore.h"
#include "Common/PlatformLayer.h"
-
-//temp include
-#include "ContextRepository.h"
-#include "ContextExecutor.h"
+#include "Common/InternalInterface.h"
/**
- * @class CResponseReactor
- * @brief Class for implement of reactor pattern
- * Delegate requested context to context executor layer.
+ * @class CSensingEngine
+ * @brief Class for implementing main abstration of SensorProcessor
*
*
* @see
*/
-class CResponseReactor :
+class CSensingEngine :
public CObjectRoot<CObjectMultiThreadModel>
- , public IResponseReactor
+ , public ISensingEngine
{
private:
CObjectPtr<IContextRepository> m_pContextRepository;
CSimpleMutex m_mtxUnregisterContext;
public:
-
SSMRESULT finalConstruct();
void finalRelease();
if (ppObject == NULL)
return SSM_E_POINTER;
- if (IsEqualOID(objectID, OID_IResponseReactor))
+ if (IsEqualOID(objectID, OID_ISensingEngine))
{
IBase *pBase = this;
pBase->addRef();
* @param [in] ISSMResource *pSSMResource - Requested context model resource.
* @param [in] IEvent *pEvent - IEvent class for callback.
*
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- void registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+ SSMRESULT registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+ IN IEvent *pEvent);
/**
* @fn unregisterContext
* @param [in] ISSMResource *pSSMResource - Requested context model resource.
* @param [in] IEvent *pEvent - IEvent class for callback.
*
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- void unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+ SSMRESULT unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+ IN IEvent *pEvent);
/**
* @fn getList
*
* @param [out] std::vector<ISSMResource> *pList - ISSMResource vector of low level context models or high level context models.
*
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- virtual void getList(OUT std::vector<ISSMResource *> *pList);
+ SSMRESULT getList(OUT std::vector<ISSMResource *> *pList);
/**
* @fn onEvent
*/
int onEvent(IN std::string name, IN TypeofEvent callType, IN std::vector<ContextData> ctxData);
};
-
-
-#endif
+#endif
\ No newline at end of file
-
+-include ../../build/linux/root_path.inc
-include ../../build/linux/environment.mk
MAKE=make
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
RST_NAME=release
# Insert your project name.
-TARGET=ClientApp
+TARGET=SSMTesterApp
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+
+CXX_LIB+=${OUTPUTS_DIR}/${SSM_LIB}
+CXX_LIB+=${OUTPUTS_DIR}/${SSMCORE_LIB}
CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB}
-CXX_LIB+=-lpthread
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
+CXX_LIB+=-lpthread -ldl
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
OBJPATH=${SRCLIST:.cpp=.o}
pre_job:
@echo " "
- @echo "--------- ClientApp Build Begin. -----------"
+ @echo "--------- ${TARGET} Build Begin. -----------"
@mkdir -p ${RST_NAME}
@echo " "
-${TARGET}: ${OBJLIST} ${OUTPUTS_DIR}/SSMClient.o
+${TARGET}: ${OBJLIST}
$(CXX) $(CXX_FLAGS) -o ./${RST_NAME}/$@ $^ ${CXX_LIB}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
- @echo "----------- ClientApp Build Successful. ------------"
+ @echo "----------- ${TARGET} Build Successful. ------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
#include "OCResource.h"
#include "OCPlatform.h"
+#include "SSMInterface.h"
#include "SSMClient.h"
#include "ISSMClientListener.h"
} DIResult;
class SSMTestApp: public ISSMClientListener
+ , public IQueryEngineEvent
{
private:
- SSMClient m_SSMClient;
+ //SSMClient m_SSMClient;
+ SSMInterface m_SSMClient;
public:
/* operations from listener interface */
void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode);
-
+ SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult);
};
#endif /* SSMTESTAPP_H_ */
#include <iostream>
#include "SSMTestApp.h"
-#include "SSMClient.h"
SSMTestApp::SSMTestApp()
{
/* Register Query.*/
void SSMTestApp::registerQuery(std::string queryString)
{
- std::string qid;
- SSMReturn rtn = SSM_ERROR;
+ int qid;
+ SSMRESULT rtn = SSM_E_FAIL;
if (queryString.size() == 0)
{
rtn = m_SSMClient.registerQuery(queryString, this, qid);
- if (rtn == SSM_SUCCESS)
+ if (rtn == SSM_S_OK)
{
printf("The query has been registered!\n");
- printf("QID : %s\n", qid.c_str());
+ printf("QID : %d\n", qid);
}
else
printf("Error occured(%d)", rtn);
void SSMTestApp::unregisterQuery(void)
{
std::string qid;
- SSMReturn rtn = SSM_ERROR;
+ SSMRESULT rtn = SSM_E_FAIL;
printf(" Please Enter query string: ");
cin.ignore();
getline(cin, qid);
- rtn = m_SSMClient.unregisterQuery(qid);
+ rtn = m_SSMClient.unregisterQuery(atoi(qid.c_str()));
- if (rtn == SSM_SUCCESS)
+ if (rtn == SSM_S_OK)
printf("The query has been unregistered!\n");
else
printf("Error occured(%d)\n", (int) rtn);
{
if (strcmp(itor->first.c_str(), "temperature") == 0)
{
- std::cout << "* Temperature : " << itor->second.front().c_str() << "℃" << std::endl;
+ std::cout << "* Temperature : " << itor->second.c_str() << "℃" << std::endl;
}
else if (strcmp(itor->first.c_str(), "humidity") == 0)
{
- std::cout << "* Humidity : " << itor->second.front().c_str() << "%" << std::endl;
+ std::cout << "* Humidity : " << itor->second.c_str() << "%" << std::endl;
}
else if (strcmp(itor->first.c_str(), "discomfortIndex") == 0)
{
- int DI = std::stoi(itor->second.front().c_str());
+ int DI = std::stoi(itor->second.c_str());
std::cout << "* DiscomfortIndex : " << DI << "%" << std::endl;
}
}
+SSMRESULT SSMTestApp::onQueryEngineEvent(int cqid, IDataReader *pResult)
+{
+ int dataCount = 0;
+ IModelData *pModelData = NULL;
+ std::vector<std::string> affectedModels;
+
+ cout << "Event received! cqid = " << cqid << endl;
+
+ pResult->getAffectedModels(&affectedModels);
+
+ for (std::vector<std::string>::iterator itor = affectedModels.begin();
+ itor != affectedModels.end(); ++itor)
+ {
+ cout << "Printing " << *itor << " model" << endl;
+ pResult->getModelDataCount(*itor, &dataCount);
+ for (int i = 0; i < dataCount; i++)
+ {
+ pResult->getModelData(*itor, i, &pModelData);
+ cout << "dataId: " << pModelData->getDataId() << endl;
+ for (int j = 0; j < pModelData->getPropertyCount(); j++)
+ {
+ cout << "Type: " << pModelData->getPropertyName(j) << " Value: " << pModelData->getPropertyValue(
+ j) << endl;
+ }
+ }
+ }
+
+ return SSM_S_OK;
+}
+
/**
* APP. Main Function.
*/
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB}
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
CXX_LIB+=-lpthread
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
pre_job:
@echo " "
- @echo "---------- THSensorApp Build Begin. ------------"
+ @echo "---------- ${TARGET} Build Begin. ------------"
@mkdir -p ${RST_NAME}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
- @echo "----------- THSensorApp Build Successful. -------------"
+ @echo "----------- ${TARGET} Build Successful. -------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
#include <string>
#include <cstdlib>
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 56830
+#define COAP_IP "0.0.0.0"
+#define COAP_PORT 0
#define COAP_MODE ModeType::Server
#define COAP_SRVTYPE ServiceType::InProc
/// Access this property from a TB client
int m_humid;
int m_temp;
- string m_resourceUri;
+ std::string m_resourceUri;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_resourceInterfaces;
OCResourceHandle m_resourceHandle;
+ OCRepresentation m_resourceRep;
+ ObservationIds m_interestedObservers;
public:
/// Constructor
TemphumidResource() :
- m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor"), m_resourceHandle(NULL)
+ m_humid(0), m_temp(0)
{
+ m_resourceUri = "/Thing_TempHumSensor";
+ m_resourceTypes.push_back(COAP_TYPE_NAME);
+ m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+ printf("Running thing as %s\n", m_resourceUri.c_str());
+ m_resourceRep.setUri(m_resourceUri);
+ m_resourceRep.setResourceTypes(m_resourceTypes);
+ m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
}
~TemphumidResource()
{
}
- void registerResource(OC::OCPlatform &platform);
+ void registerResource();
OCResourceHandle getHandle();
- void setRepresentation(AttributeMap &attributeMap);
+ void setResourceRepresentation(OCRepresentation &rep);
- void getRepresentation(AttributeMap &attributeMap);
+ OCRepresentation getResourceRepresentation();
};
#endif /* THINGRESOURCESERVER_H_ */
int g_Observation = 0;
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+ std::shared_ptr< OCResourceResponse > response);
/*
* TempResourceFunctions
*/
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
{
- string resourceURI = m_resourceUri; // URI of the resource
- string resourceTypeName = COAP_TYPE_NAME; // resource type name.
- string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
// This will internally create and register the resource.
- OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
- resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+ OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+ m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
if (OC_STACK_OK != result)
{
return m_resourceHandle;
}
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
{
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
- cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+ int tempHumid;
+ int tempTemp;
+
+ rep.getValue("2", tempTemp);
+ rep.getValue("5", tempHumid);
- m_temp = std::stoi(attributeMap["temp"][0]);
- m_humid = std::stoi(attributeMap["humid"][0]);
+ m_humid = tempHumid;
+ m_temp = tempTemp;
+
+ cout << "\t\t\t" << "Received representation: " << endl;
+ cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+ cout << "\t\t\t\t" << "humid: " << m_temp << endl;
}
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
{
- attributeMap["0"].push_back("temperature");
- attributeMap["1"].push_back("int");
-
- attributeMap["2"].push_back(to_string(m_temp));
- attributeMap["3"].push_back("humidity");
- attributeMap["4"].push_back("int");
+ // This representation is temporaily for soft-sensor-management - name, type, vale
+ m_resourceRep.setValue("0", std::string("temperature"));
+ m_resourceRep.setValue("1", std::string("int"));
+ m_resourceRep.setValue("2", std::to_string(m_temp));
+ m_resourceRep.setValue("3", std::string("humidity"));
+ m_resourceRep.setValue("4", std::string("int"));
+ m_resourceRep.setValue("5", std::to_string(m_humid));
- attributeMap["5"].push_back(to_string(m_humid));
+ return m_resourceRep;
}
+// Create the instance of the TemphumidResource class
TemphumidResource g_myResource;
void *TestSensorVal(void *param)
cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
<< endl;
- OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+ OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
if (OC_STACK_NO_OBSERVERS == result)
{
return NULL;
}
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+ std::shared_ptr< OCResourceResponse > response)
{
cout << "\tIn Server CPP entity handler:\n";
{
// Get the request type and request flag
std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+ int requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == RequestHandlerFlag::InitFlag)
+ if (requestFlag & RequestHandlerFlag::InitFlag)
{
cout << "\t\trequestFlag : Init\n";
// entity handler to perform resource initialization operations
}
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
{
cout << "\t\trequestFlag : Request\n";
cout << "\t\t\trequestType : GET\n";
// Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
// Process query params and do required operations ..
// Get the representation of this resource at this point and send it as response
- OCRepresentation rep = request->getResourceRepresentation();
- AttributeMap attributeMap;
-
- g_myResource.getRepresentation(attributeMap);
+ OCRepresentation rep = g_myResource.getResourceRepresentation();
if (response)
{
// TODO Error Code
- rep.setAttributeMap(attributeMap);
response->setErrorCode(200);
response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
}
// DELETE request operations
}
}
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
{
pthread_t threadId;
{
std::cout << "Request invalid" << std::endl;
}
+
+ return OC_EH_OK;
}
int main()
{
// Create PlatformConfig object
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+ PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
try
{
- OCPlatform platform(cfg);
+ OC::OCPlatform::Configure(cfg);
- g_myResource.registerResource(platform);
+ g_myResource.registerResource();
int input = 0;
cout << "Type any key to terminate" << endl;
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB}
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
CXX_LIB+=-lpthread
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
pre_job:
@echo " "
- @echo "---------- THSensorApp Build Begin. ------------"
+ @echo "---------- ${TARGET} Build Begin. ------------"
@mkdir -p ${RST_NAME}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
- @echo "----------- THSensorApp Build Successful. -------------"
+ @echo "----------- ${TARGET} Build Successful. -------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
#include <string>
#include <cstdlib>
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 56838
+#define COAP_IP "0.0.0.0"
+#define COAP_PORT 0
#define COAP_MODE ModeType::Server
#define COAP_SRVTYPE ServiceType::InProc
/// Access this property from a TB client
int m_humid;
int m_temp;
- string m_resourceUri;
+ std::string m_resourceUri;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_resourceInterfaces;
OCResourceHandle m_resourceHandle;
+ OCRepresentation m_resourceRep;
+ ObservationIds m_interestedObservers;
public:
/// Constructor
TemphumidResource() :
- m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor1"), m_resourceHandle(NULL)
+ m_humid(0), m_temp(0)
{
+ m_resourceUri = "/Thing_TempHumSensor1";
+ m_resourceTypes.push_back(COAP_TYPE_NAME);
+ m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+ printf("Running thing as %s\n", m_resourceUri.c_str());
+ m_resourceRep.setUri(m_resourceUri);
+ m_resourceRep.setResourceTypes(m_resourceTypes);
+ m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
}
~TemphumidResource()
{
}
- void registerResource(OC::OCPlatform &platform);
+ void registerResource();
OCResourceHandle getHandle();
- void setRepresentation(AttributeMap &attributeMap);
+ void setResourceRepresentation(OCRepresentation &rep);
- void getRepresentation(AttributeMap &attributeMap);
+ OCRepresentation getResourceRepresentation();
};
#endif /* THINGRESOURCESERVER_H_ */
int g_Observation = 0;
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+ std::shared_ptr< OCResourceResponse > response);
/*
- * TempResourceFunctions
- */
+* TempResourceFunctions
+*/
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
{
- string resourceURI = m_resourceUri; // URI of the resource
- string resourceTypeName = COAP_TYPE_NAME; // resource type name.
- string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
// This will internally create and register the resource.
- OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
- resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+ OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+ m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
if (OC_STACK_OK != result)
{
return m_resourceHandle;
}
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
{
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
- cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+ int tempHumid;
+ int tempTemp;
+
+ rep.getValue("2", tempTemp);
+ rep.getValue("5", tempHumid);
- m_temp = std::stoi(attributeMap["temp"][0]);
- m_humid = std::stoi(attributeMap["humid"][0]);
+ m_humid = tempHumid;
+ m_temp = tempTemp;
+
+ cout << "\t\t\t" << "Received representation: " << endl;
+ cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+ cout << "\t\t\t\t" << "humid: " << m_temp << endl;
}
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
{
- attributeMap["0"].push_back("temperature");
- attributeMap["1"].push_back("int");
-
- attributeMap["2"].push_back(to_string(m_temp));
- attributeMap["3"].push_back("humidity");
- attributeMap["4"].push_back("int");
+ // This representation is temporaily for soft-sensor-management - name, type, vale
+ m_resourceRep.setValue("0", std::string("temperature"));
+ m_resourceRep.setValue("1", std::string("int"));
+ m_resourceRep.setValue("2", std::to_string(m_temp));
+ m_resourceRep.setValue("3", std::string("humidity"));
+ m_resourceRep.setValue("4", std::string("int"));
+ m_resourceRep.setValue("5", std::to_string(m_humid));
- attributeMap["5"].push_back(to_string(m_humid));
+ return m_resourceRep;
}
+// Create the instance of the TemphumidResource class
TemphumidResource g_myResource;
void *TestSensorVal(void *param)
cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
<< endl;
- OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+ OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
if (OC_STACK_NO_OBSERVERS == result)
{
return NULL;
}
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+ std::shared_ptr< OCResourceResponse > response)
{
cout << "\tIn Server CPP entity handler:\n";
{
// Get the request type and request flag
std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+ int requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == RequestHandlerFlag::InitFlag)
+ if (requestFlag & RequestHandlerFlag::InitFlag)
{
cout << "\t\trequestFlag : Init\n";
// entity handler to perform resource initialization operations
}
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
{
cout << "\t\trequestFlag : Request\n";
cout << "\t\t\trequestType : GET\n";
// Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
// Process query params and do required operations ..
// Get the representation of this resource at this point and send it as response
- OCRepresentation rep = request->getResourceRepresentation();
- AttributeMap attributeMap;
-
- g_myResource.getRepresentation(attributeMap);
+ OCRepresentation rep = g_myResource.getResourceRepresentation();
if (response)
{
// TODO Error Code
- rep.setAttributeMap(attributeMap);
response->setErrorCode(200);
response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
}
// DELETE request operations
}
}
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
{
pthread_t threadId;
if (!startedThread)
{
- pthread_create(&threadId, NULL, TestSensorVal, (void *) NULL);
+ pthread_create(&threadId, NULL, TestSensorVal, (void *)NULL);
startedThread = 1;
}
}
{
std::cout << "Request invalid" << std::endl;
}
+
+ return OC_EH_OK;
}
int main()
{
// Create PlatformConfig object
-
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+ PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
try
{
- OCPlatform platform(cfg);
+ OC::OCPlatform::Configure(cfg);
- g_myResource.registerResource(platform);
+ g_myResource.registerResource();
int input = 0;
cout << "Type any key to terminate" << endl;
+++ /dev/null
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(oic)
-
-SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
-SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
-SET(EX_SERVER "simpleserver")
-SET(EX_CLIENT "simpleclient")
-SET(EX_CLIENTSERVER "simpleclientserver")
-SET(OCTBSTACK "octbstack")
-
-INCLUDE_DIRECTORIES(include)
-INCLUDE_DIRECTORIES(csdk/stack/include)
-INCLUDE_DIRECTORIES(csdk/ocsocket/include)
-INCLUDE_DIRECTORIES(csdk/ocrandom/include)
-INCLUDE_DIRECTORIES(csdk/logger/include)
-INCLUDE_DIRECTORIES(csdk/libcoap-4.1.1)
-INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
-LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
-
-#SET(EXTRA_CXXFLAGS "-std=c++11")
-SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
-
-SET(SRCS
- OCLib/OCReflect.cpp
- OCLib/OCPlatform.cpp
- OCLib/OCResource.cpp
- OCLib/OCUtilities.cpp
- OCLib/InProcServerWrapper.cpp
- OCLib/InProcClientWrapper.cpp)
-ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
-
-ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_SUBDIRECTORY(csdk)
-#ADD_SUBDIRECTORY(examples)
-ADD_SUBDIRECTORY(oic-sample)
+++ /dev/null
-#!/bin/bash
-
-# Prevent Support Tool(Defect analysis and commit) Execution Batch File!!
-
-# variables
-SDBPATH=/home/iotivity/tizen-sdk/tools/sdb
-GBSRPMPATH=/home/iotivity/GBS-ROOT/rsa/local/repos/rsa/armv7l/RPMS
-PACKAGE=oic-0.0.1-0.armv7l.rpm
-
-gbs build -A armv7l --include-all --ccache
-
-$SDBPATH root on
-
-$SDBPATH push $GBSRPMPATH/$PACKAGE /root/
-
-$SDBPATH shell rpm -Uvh --force /root/oic-0.0.1-0.armv7l.rpm
-
-$SDBPATH shell /usr/apps/com.samsung.oicapp-test/bin/oicapp-test
+++ /dev/null
-com.samsung.oicapp-test system::use_internet r
-
-system::use_internet com.samsung.oicapp-test r
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.oicapp-test" version="0.1.0" install-location="internal-only">
- <label>OIC tset</label>
- <author email="email@samsung.com" href="www.samsung.com">Name</author>
- <description>OIC test Application</description>
- <ui-application appid="com.samsung.oicapp-test" exec="/usr/apps/com.samsung.oicapp-test/bin/oicapp-test" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
- <icon>com.samsung.oicapp-test.png</icon>
- <label>OIC test</label>
- </ui-application>
-</manifest>
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics 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 ISSMClientListener.h
- * @brief This file contains client listener interfaces.
- */
-
-#ifndef ISSMCLIENTLISTENER_H_
-#define ISSMCLIENTLISTENER_H_
-#include <string>
-#include "OCPlatform.h"
-
-/**
- * @brief This enum defines Soft Sensor return types
- */
-typedef enum
-{
- SSM_SUCCESS, SSM_ERROR, SSM_ERROR_QUERY_PARSING, SSM_ERROR_NO_QUERY, SSM_ERROR_NETWORK
-} SSMReturn;
-
-using namespace OC;
-/**
- * @brief ISSMClientListener is a listener interface from which application is derived to get callback from SoftSensorManager service
- */
-class ISSMClientListener
-{
- public:
- /**
- * @brief onRegisterQuery is a pure virtual operation which should be implemented in applications to get callback messages.
- * @param [in] attributeMap - A data map in which SoftSensorManager service sends sensor data with cqid.
- * @param [in] eCode - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
- * SSMClient can callback message to the appication.
- * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
- * @return SSMReturn
-
- */
- virtual void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode) = 0;
- virtual ~ISSMClientListener()
- {
- }
-};
-
-#endif /* ISSMCLIENTLISTENER_H_ */
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics 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.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <iostream>
-#include <string>
-
-#include "SSMClient.h"
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-const char *SSM_RESOURCE_URI = "/service/SoftSensorManager";
-
-#define SSM_RESOURCE_TYPE = "core.SoftSensorManager"
-
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 5683
-#define COAP_MODE ModeType::Client
-#define COAP_SRVTYPE ServiceType::InProc
-
-#define COAP_SERVER_ADDR "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
-
-SSMClient::SSMClient()
-{
- m_sem.create(100000);
- m_pPlatform = NULL;
- m_appListener = NULL;
- m_retResponse = SSM_ERROR;
- _findResource();
- _createQueryEngine();
-}
-
-SSMClient::~SSMClient()
-{
- _releaseQueryEngine(m_queryEngineId);
- if (m_pPlatform)
- {
- delete m_pPlatform;
- m_pPlatform = NULL;
- }
-}
-
-void SSMClient::_findResource()
-{
- // Create PlatformConfig object
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::Confirmable);
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
- try
- {
- m_pPlatform = new OCPlatform(cfg);
-
- // Find all resources
- OCStackResult result;
- if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
- std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
- != OC_STACK_OK)
- {
- delete m_pPlatform;
- m_pPlatform = NULL;
- return;
- }
-
- m_sem.wait();
-
- }
- catch (OCException e)
- {
- //log(e.what());
- }
-}
-
-void SSMClient::_createQueryEngine(void)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("CreateQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- rep.setAttributeMap(requestAttributeMap);
-
- if (m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
- {
- return;
- }
-
- m_sem.wait();
-}
-
-void SSMClient::_releaseQueryEngine(std::string queryEngineId)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("ReleaseQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- rep.setAttributeMap(requestAttributeMap);
-
- m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2));
-
- m_sem.wait();
-}
-
-SSMReturn SSMClient::registerQuery(std::string queryString, ISSMClientListener *listener,
- std::string &cqid)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues contextQueryValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("ExecuteContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- contextQueryValue.push_back(queryString);
-
- requestAttributeMap["contextQuery"] = contextQueryValue;
-
- m_appListener = listener;
-
- rep.setAttributeMap(requestAttributeMap);
-
- if (m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
- return SSM_ERROR_NETWORK;
-
- m_sem.wait();
-
- if (m_retResponse == SSM_SUCCESS)
- {
- cqid = m_responseAttributeMap["CQID"].back();
- }
-
- return m_retResponse;
-}
-
-SSMReturn SSMClient::unregisterQuery(std::string cqid)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues cqidValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("KillContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- cqidValue.push_back(cqid);
-
- requestAttributeMap["CQID"] = cqidValue;
-
- rep.setAttributeMap(requestAttributeMap);
-
- if (m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
- return SSM_ERROR_NETWORK;
-
- m_sem.wait();
-
- return m_retResponse;
-}
-
-/**
- * Callback Function List.
- */
-// Callback to found resources
-void SSMClient::onFoundResource(std::shared_ptr< OCResource > resource)
-{
- std::string resourceURI;
- try
- {
- // Do some operations with resource object.
- if (resource)
- {
- // Get the resource URI
- resourceURI = resource->uri();
-
- if (resourceURI.compare(SSM_RESOURCE_URI) == 0)
- {
- m_SSMResource = resource;
- }
- }
- }
- catch (std::exception &e)
- {
- //log(e.what());
- }
-
- m_sem.release();
-}
-
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
-{
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
- m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
- m_responseAttributeMap["queryEngineId"].pop_back();
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
-{
- QueryParamsMap queryParamsMap;
-
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
-
- if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
- {
- m_retResponse = SSM_ERROR_QUERY_PARSING;
- goto CLEANUP;
- }
-
- m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
- std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
-
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
-{
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
-
- if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
- {
- m_retResponse = SSM_ERROR_NO_QUERY;
- goto CLEANUP;
- }
-
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
-{
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
-
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
-{
- SSMReturn ret = SSM_SUCCESS;
-
- if (eCode != 0)
- {
- ret = SSM_ERROR_NETWORK;
- }
-
- m_appListener->onRegisterQuery(rep.getAttributeMap(), ret);
-}
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics 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 SSMClient.h
- * @brief This file contains the declaration of classes and its members related to SSMClient.
- */
-
-#ifndef RESOURCECLIENT_H_
-#define RESOURCECLIENT_H_
-
-#include <string>
-
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "ISSMClientListener.h"
-
-using namespace OC;
-
-#if defined(WIN32)
-class CSemaphore
-{
- private:
- HANDLE hSemaphore;
- int m_MaxTimeOut;
-
- public:
- /**
- * This is CSemaphore constructor.
- */
- CSemaphore()
- {
- m_MaxTimeOut = 0;
- }
- /**
- *This is CSemaphore destructor.
- */
- ~CSemaphore()
- {
- }
-
- /**
- * This is a function to creat a semaphore
- * This is syncronus call.
- * @param maximumRequestTimeOut
- * [IN] Request Time out.
- *
- * @return None
- *
- */
- void create(int maximumRequestTimeOut)
- {
- hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
- m_MaxTimeOut = maximumRequestTimeOut;
- }
-
- /**
- * This is a function to wait for semaphore
- *
- * @return None
- *
- */
- void wait()
- {
- WaitForSingleObject(hSemaphore, m_MaxTimeOut);
- }
-
- /**
- * This is a function to release semaphore
- *
- * @return None
- *
- */
- void release()
- {
- ReleaseSemaphore(hSemaphore, 1, NULL);
- }
-
-};
-
-#elif defined(LINUX)
-#include <semaphore.h>
-
-#define SEM_SUCCESS 0
-
-class CSemaphore
-{
- private:
- sem_t hSemaphore;
- timespec m_MaxTimeOut;
-
- public:
- /**
- * This is CSemaphore constructor.
- */
- CSemaphore()
- {
- m_MaxTimeOut.tv_sec = 0;
- m_MaxTimeOut.tv_nsec = 0;
- }
- /**
- *This is CSemaphore destructor.
- */
- ~CSemaphore()
- {
- }
- /**
- * This is a function to creat a semaphore
- * This is syncronus call.
- * @param maximumRequestTimeOut
- * [IN] Request Time out.
- *
- * @return None
- *
- */
- void create(int maximumRequestTimeOut)
- {
- if ( sem_init(&hSemaphore, 1, 0) < SEM_SUCCESS )
- {
- perror("Error : sem_init.");
- exit(0);
- }
- m_MaxTimeOut.tv_sec = maximumRequestTimeOut;
- }
-
- void wait()
- {
- sem_wait( &hSemaphore );
- }
-
- /**
- * This is a function to release semaphore
- *
- * @return None
- *
- */
- void release()
- {
- sem_post(&hSemaphore);
- }
-
-};
-#endif
-
-/**
- * @brief SSMClient is a wrapper class to provide SoftSensorManager functionality to Application.
- * Basically, SoftSensorManager is developed in Resource model (i.e. messaging with basic functions of put, get, and post).
- * SSMClient abstracts the resource based operations from client applications and provides c++ style functions.
- */
-class SSMClient
-{
- private:
- SSMReturn m_retResponse;
- OCPlatform *m_pPlatform;
- CSemaphore m_sem;
- /**
- * @brief SoftSensorManager Resource.
- */
- std::shared_ptr< OCResource > m_SSMResource;
- /**
- * @brief attribute map .
- */
- AttributeMap m_responseAttributeMap;
- /**
- * @brief query engine.
- */
- std::string m_queryEngineId;
- /**
- * @brief app listener
- */
- ISSMClientListener *m_appListener;
-
- /**
- * @brief internal find resource function
- */
- void _findResource(void);
-
- /**
- * @brief internal Query engine function
- */
- void _createQueryEngine(void);
-
- /**
- * @brief internal release query function
- */
- void _releaseQueryEngine(std::string queryEngineId);
-
- public:
- /**
- * Constructor for SSMClient.
- */
- SSMClient();
- ~SSMClient();
-
- /**
- * This API sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
- *
- * @param [in] queryString - A conditions query statement where the caller application specifies sensors for required data and conditions when the caller wants to get the data.
- * @param [in] listener - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
- * SSMClient can callback message to the application.
- * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
- * @return SSMReturn
-
- */
- SSMReturn registerQuery(std::string queryString, ISSMClientListener *listener,
- std::string &cqid);
- /**
- * This API is to cancel the registered sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
- *
- * @param [in] listener - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
- * SSMClient can callback message to the application.
- * @param [in] cqid - A query id generated from SoftSensorManager service for the queryString request.
- * @return SSMReturn
- */
- SSMReturn unregisterQuery(std::string cqid);
-
- // friend option. for callback from SSMResource
- void onFoundResource(std::shared_ptr< OCResource > resource);
- void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
- void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
- void onRegisterQuery(const OCRepresentation &rep, const int eCode);
- void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
- void onObserve(const OCRepresentation &rep, const int &eCode);
-};
-
-#endif /* RESOURCECLIENT_H_ */
+++ /dev/null
-[Unit]
-Description=OIC
-After=deviced.service
-
-[Service]
-Type=simple
-ExecStart=/usr/bin/simpleserver
-TimeoutStopSec=1s
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(ssm)
+
+SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
+SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
+#SET(EX_SERVER "simpleserver")
+#SET(EX_CLIENT "simpleclient")
+#SET(EX_CLIENTSERVER "simpleclientserver")
+#SET(OCTBSTACK "octbstack")
+
+#INCLUDE_DIRECTORIES(include)
+#INCLUDE_DIRECTORIES(csdk/stack/include)
+#INCLUDE_DIRECTORIES(csdk/ocsocket/include)
+#INCLUDE_DIRECTORIES(csdk/ocrandom/include)
+#INCLUDE_DIRECTORIES(csdk/logger/include)
+#INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
+#LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
+
+#SET(EXTRA_CXXFLAGS "-std=c++11")
+#SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
+
+#SET(SRCS
+# OCLib/OCReflect.cpp
+# OCLib/OCPlatform.cpp
+# OCLib/OCResource.cpp
+# OCLib/InProcServerWrapper.cpp
+# OCLib/InProcClientWrapper.cpp)
+#ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
+
+#ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_SUBDIRECTORY(csdk)
+#ADD_SUBDIRECTORY(examples)
+ADD_SUBDIRECTORY(oic-sample)
-SET(TESTAPP "oicapp-test")
+SET(TESTAPP "ssmtester")
FILE(GLOB SRCS src/*.c src/*.cpp)
SET(VENDOR "samsung")
SET(PACKAGE ${TESTAPP})
SET(PKGNAME "com.${VENDOR}.${PACKAGE}")
-SET(PREFIX "/usr/apps/com.samsung.oicapp-test")
+SET(PREFIX "/usr/apps/com.samsung.ssmtester")
SET(BINDIR "${PREFIX}/bin")
SET(RESDIR "${PREFIX}/res")
SET(DATADIR "${PREFIX}/data")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lib)
+
ADD_EXECUTABLE(${TESTAPP} ${SRCS})
-TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ssmcore oc octbstack oc_logger oc_logger_core pthread dl)
INSTALL(TARGETS ${TESTAPP} DESTINATION ${BINDIR})
--- /dev/null
+com.samsung.ssmtester system::use_internet r
+
+system::use_internet com.samsung.ssmtester r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.ssmtester" version="0.1.0" install-location="internal-only">
+ <label>OIC test</label>
+ <author email="email@samsung.com" href="www.samsung.com">Name</author>
+ <description>SSM test Application</description>
+ <ui-application appid="com.samsung.ssmtester" exec="/usr/apps/com.samsung.ssmtester/bin/ssmtester" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
+ <icon>com.samsung.oicapp-test.png</icon>
+ <label>SSM test</label>
+ </ui-application>
+</manifest>
#include <efl_assist.h>
#include <string>
+#include <sstream>
#include "oicapp-test.h"
#include "oicapp-utils.h"
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "SSMClient.h"
-#include "ISSMClientListener.h"
+#include "SSMInterface.h"
static oicapp_data *g_ad = NULL;
-class CSSMClientListener: public ISSMClientListener
+int g_CQID = 9999;
+
+class CQueryEngineEvent : public IQueryEngineEvent
{
public:
- void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn::SSMReturn &eCode)
- {
- //EFL UI printing
- char *queryResult = "";
+ SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult)
+ {
std::stringstream sstream;
- for (AttributeMap::const_iterator itor = attributeMap.begin(); itor != attributeMap.end(); itor++)
+ int dataCount = 0;
+ IModelData *pModelData = NULL;
+ std::vector<std::string> affectedModels;
+
+ pResult->getAffectedModels(&affectedModels);
+
+ for (std::vector<std::string>::iterator itor = affectedModels.begin();
+ itor != affectedModels.end(); ++itor)
{
- //if (itor->first == "queryEngineId")
- //{
- // sstream << itor->first.c_str() << " : " << std::hex << stoi(itor->second.front().c_str()) << "\n";
- //}
- //else
- //{
- sstream << itor->first.c_str() << " : " << itor->second.front().c_str() << "\n";
- //}
+ printf("Printing %s\n", itor->c_str());
+ pResult->getModelDataCount(*itor, &dataCount);
+ for (int i = 0; i < dataCount; i++)
+ {
+ pResult->getModelData(*itor, i, &pModelData);
+ printf("dataId: %d\n", pModelData->getDataId());
+ for (int j = 0; j < pModelData->getPropertyCount(); j++)
+ {
+ sstream << "Type: " << pModelData->getPropertyName(j).c_str() <<
+ " Value: " << pModelData->getPropertyValue(j).c_str() << "<br>";
+ }
+ }
}
-// queryResult = const_cast<char *>(sstream .str().c_str());
- oicapp_util_put_msg (g_ad, g_ad->input_msg);
+ sstream << std::ends;
+ oicapp_util_put_msg(g_ad, sstream.str().c_str());
+ return SSM_S_OK;
}
};
-CSSMClientListener *g_SSMClientListener = new CSSMClientListener();
-SSMClient *g_SSMClient = NULL;
+CQueryEngineEvent *g_SSMClientListener = new CQueryEngineEvent();
+SSMInterface *g_SSMClient = new SSMInterface();
static Elm_Object_Item *oicapp_append_separator(Evas_Object *genlist,
oicapp_data *ad)
item = elm_genlist_item_append(genlist, &ad->itc_seperator, NULL, NULL,
ELM_GENLIST_ITEM_NONE, NULL, NULL);
- elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
+ //elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
return item;
}
static void oicapp_append_contents(oicapp_data *ad)
{
Elm_Object_Item *item;
-
+ /*
oicapp_append_separator(ad->genlist, ad);
_gl_append_item(ad, &ad->itc_edit);
ad->item_multiline = item;
oicapp_append_separator(ad->genlist, ad);
+ */
+ oicapp_append_separator(ad->genlist, ad);
+
+ elm_genlist_item_append(ad->genlist, &ad->itc_edit, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ elm_genlist_item_append(ad->genlist, &ad->itc_btn, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ item = _gl_append_item(ad, &ad->itc_multiline);
+
+ ad->item_multiline = item;
+
+ oicapp_append_separator(ad->genlist, ad);
}
static Evas_Object *oicapp_create_conform(Evas_Object *win)
{
oicapp_data *ad = (oicapp_data *)data;
- std::string cqid;
+ std::string str = std::string(ad->input_msg);
+
+ std::string strGT = ">";
+
+ std::string strLT = "<";
+
+ std::size_t foundGT = str.find(strGT);
- g_SSMClient->registerQuery(std::string(ad->input_msg), g_SSMClientListener, cqid);
+ std::size_t foundLT = str.find(strLT);
+
+ std::stringstream sstream;
+
+ if (foundGT != std::string::npos)
+ {
+ str.replace(foundGT, strGT.length(), ">");
+ }
+
+ if (foundLT != std::string::npos)
+ {
+ str.replace(foundLT, strLT.length(), "<");
+ }
+
+ g_SSMClient->registerQuery(str, g_SSMClientListener, g_CQID);
+
+ sstream << "Query executed! cqid = " << g_CQID << std::ends;
+
+ oicapp_util_put_msg(ad, sstream.str().c_str());
ERR("button clicked(%s)", ad->input_msg);
}
ad->input_msg = strdup(elm_entry_entry_get(obj));
-// oicapp_util_put_msg(ad, ad->input_msg);
-
DBG("Clicked : %s", ad->input_msg);
}
return entry;
}
+static char *_item_Text_get(void *data, Evas_Object *obj, const char *part)
+{
+ char *buf =
+ "subscribe Device.DiscomfortIndexSensor if Device.DiscomfortIndexSensor.discomfortIndex > 0";
+
+ return strdup(buf);
+}
+
static inline void oicapp_init_itcs(oicapp_data *ad)
{
ad->itc_seperator.item_style = "dialogue/separator";
ad->itc_seperator.func.del = NULL;
ad->itc_edit.item_style = "dialogue/editfield";
- ad->itc_edit.func.text_get = NULL;
+ ad->itc_edit.func.text_get = _item_Text_get;
ad->itc_edit.func.content_get = _gl_edit_content_get;
ad->itc_edit.func.state_get = NULL;
ad->itc_edit.func.del = NULL;
ad->itc_multiline.item_style = "multiline/1text";
ad->itc_multiline.func.text_get = _gl_multiline_text_get;
- //ad->itc_multiline.func.text_get = NULL;
ad->itc_multiline.func.content_get = NULL;
ad->itc_multiline.func.state_get = NULL;
ad->itc_multiline.func.del = NULL;
ad->genlist = oicapp_create_genlist(ad->navi);
- it = elm_naviframe_item_push(ad->navi, "OIC Tester", NULL, NULL, ad->genlist, NULL);
+ it = elm_naviframe_item_push(ad->navi, "SSM Tester", NULL, NULL, ad->genlist, NULL);
elm_naviframe_item_pop_cb_set(it, _back_cb, ad);
ad->ip_addr = oicapp_util_wifi();
oicapp_append_contents(ad);
- g_SSMClient = new SSMClient();
-
return 0;
}
{
oicapp_data *ad = (oicapp_data *)data;
+ if (g_CQID != 9999)
+ g_SSMClient->unregisterQuery(g_CQID);
+
if (ad->win)
evas_object_del(ad->win);
DBG("Output msg : %s", ad->output_msg);
elm_genlist_item_update(ad->item_multiline);
+ elm_genlist_item_item_class_update(ad->item_multiline, &(ad->itc_multiline));
}
char* oicapp_util_wifi()
-Name: oic
+Name: ssm
Summary: Open Interconnect Consortium
Version: 0.0.1
Release: 0
Group: Network & Connectivity/Service
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
-Source1: %{name}.service
+Source1: libDiscomfortIndexSensor.so
+Source2: SoftSensorDescription.xml
Source1001: %{name}.manifest
BuildRequires: cmake
-BuildRequires: boost-devel
+#BuildRequires: boost-devel
#BuildRequires: pkgconfig(glib-2.0)
-Buildrequires: gettext-tools
+#Buildrequires: gettext-tools
BuildRequires: pkgconfig(appcore-efl)
BuildRequires: pkgconfig(ecore-x)
BuildRequires: pkgconfig(elementary)
%install
-rm -rf %{buildroot}/BUILD/oic*
+rm -rf %{buildroot}/BUILD/ssm*
#%make_install
+cp -af %{SOURCE1} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
+cp -af %{SOURCE2} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
%post
%files
%manifest %{name}.manifest
%defattr(-,root,root,-)
-%{_bindir}/simple*
-/usr/apps/com.samsung.oicapp-test/*
+/usr/apps/com.samsung.ssmtester/*
/usr/share/*
-/etc/smack/accesses2.d/com.samsung.oicapp-test.rule
+/etc/smack/accesses2.d/com.samsung.ssmtester.rule
#%%license LICENSE.APLv2
--- /dev/null
+<softsensors>
+
+ <softsensor>
+ <name>DiscomfortIndexSensor</name>
+ <attributes>
+ <attribute>
+ <name>version</name>
+ <type>string</type>
+ <value>1.0</value>
+ </attribute>
+ <attribute>
+ <name>lifetime</name>
+ <type>int</type>
+ <value>60</value>
+ </attribute>
+ </attributes>
+ <outputs>
+ <output>
+ <name>timestamp</name>
+ <type>string</type>
+ </output>
+ <output>
+ <name>temperature</name>
+ <type>string</type>
+ </output>
+ <output>
+ <name>humidity</name>
+ <type>string</type>
+ </output>
+ <output>
+ <name>discomfortIndex</name>
+ <type>int</type>
+ </output>
+ </outputs>
+ <inputs>
+ <input>Thing_TempHumSensor</input>
+ <input>Thing_TempHumSensor1</input>
+ </inputs>
+ </softsensor>
+
+</softsensors>
+++ /dev/null
-<high_context_dictionary>
-
- <high_context>
- <root_name>DiscomfortIndexSensor</root_name>
- <attributes>
- <attribute_property_count>2</attribute_property_count>
- <attribute_property>
- <name>version</name>
- <type>string</type>
- <value>1.0</value>
- </attribute_property>
- <attribute_property>
- <name>lifetime</name>
- <type>int</type>
- <value>60</value>
- </attribute_property>
- </attributes>
- <outputs>
- <output_property_count>4</output_property_count>
- <output_property>
- <name>timestamp</name>
- <type>string</type>
- <value>""</value>
- </output_property>
- <output_property>
- <name>temperature</name>
- <type>int</type>
- <value>0</value>
- </output_property>
- <output_property>
- <name>humidity</name>
- <type>int</type>
- <value>0</value>
- </output_property>
- <output_property>
- <name>discomfortIndex</name>
- <type>int</type>
- <value>0</value>
- </output_property>
- </outputs>
- <app_inputs>
- <app_input_count>0</app_input_count>
- </app_inputs>
- <inputs>
- <input_count>2</input_count>
- <input>Thing_TempHumSensor</input>
- <input>Thing_TempHumSensor1</input>
- </inputs>
- <enter_conditions>
- <enter_condition>
- <name>Thing_TempHumSensor</name>
- <name>Thing_TempHumSensor1</name>
- </enter_condition>
- </enter_conditions>
- </high_context>
-
-</high_context_dictionary>
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
SRC_PATH=../../src
pre_job:
@echo " "
- @echo "---------- SoftSensor Build Begin. ------------"
+ @echo "---------- ${TARGET} Build Begin. ------------"
@mkdir -p ${RST_NAME}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/lib${TARGET}.so ${OUTPUTS_DIR}/
- cp -Rdp ./HighContextDictionary.xml ${OUTPUTS_DIR}/
- @echo "-------------- SoftSensor Build Successful. -------------"
+ cp -Rdp ../../${SSXML_NAME} ${OUTPUTS_DIR}/
+ @echo "-------------- ${TARGET} Build Successful. -------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
int discomfortIndex = (int) ERROR;
double sumDI = 0.0;
+ m_result.m_temperature = "";
+ m_result.m_humidity = "";
+
for (int i = 0; i < PHYSICAL_EA; i++)
{
if (i != 0)
output_property.clear();
output_property.insert(std::make_pair("name", "temperature"));
- output_property.insert(std::make_pair("type", "int"));
+ output_property.insert(std::make_pair("type", "string"));
output_property.insert(std::make_pair("value", m_result.m_temperature));
out.outputProperty.push_back(output_property);
output_property.clear();
output_property.insert(std::make_pair("name", "humidity"));
- output_property.insert(std::make_pair("type", "int"));
+ output_property.insert(std::make_pair("type", "string"));
output_property.insert(std::make_pair("value", m_result.m_humidity));
out.outputProperty.push_back(output_property);
+IOTIVITY_DIR=${shell cd ../../../../ && pwd}
+${shell echo "ROOT_DIR=${IOTIVITY_DIR}" > ./root_path.inc}
+-include ./root_path.inc
-include ./environment.mk
MAKE=make
@echo "* *"
@echo "* It's build script for SoftSensorManagement system. *"
@echo "* Before build, Open the environment.mk file. *"
- @echo "* And, Modify ROOT_DIR path, which depend on your PC. *"
@echo "* And, Modify BOOST_BASE path, which depend on your PC. *"
@echo "* *"
@echo "*********************************************************"
clean:
-# @cd ${CUR_DIR}/../../../resource/ && make clean
-# @cd ${CUR_DIR}/../../../resource/csdk && make deepclean
-# @cd ${CUR_DIR}/9_Arduino_THSensorApp && make clean
-# @cd ${CUR_DIR}
rm -rf ./${RST_NAME}
@for subdir in ${MAKE_LIST} ; do \
echo ">>>>>>>>>>>> $${subdir}/Makefile clean run <<<<<<<<<<<<<<" ; \
${MAKE} clean -C $${subdir} ; \
echo " " ; \
done
+ rm -rf ./root_path.inc
-# root path of each PC.
-ROOT_DIR=${PWD}/../../../..
-
# boost folder path.
-BOOST_BASE=/home/iotivity/Desktop/boost_1_56_0
+BOOST_BASE=/usr/include
# ioc-resource folder path.
IOT_BASE=${ROOT_DIR}/resource
IOT_MAKE_PATH=${IOT_BASE}
IOT_RELEASE=${IOT_MAKE_PATH}/release/obj
-IOT_CSDK_RELEASE=${IOT_BASE}/csdk/release
+IOT_CSDK_RELEASE=${IOT_BASE}/csdk/linux/release
+IOT_LOG_DIR=${IOT_BASE}/oc_logger
IOT_LIB=liboc.a
IOT_CSDK_LIB=liboctbstack.a
+IOT_LOG_LIB=liboc_logger.a
# service folder path.
FD_SSM=${ROOT_DIR}/service/soft-sensor-manager
# outputs directory path.
OUTPUTS_DIR=${FD_BUILD}/linux/release
EXEC_DIR=${OUTPUTS_DIR}
-MODEL_DIR="\"${EXEC_DIR}/\""
-HIGH_LOCATION="\"${EXEC_DIR}/HighContextDictionary.xml\""
+SSXML_NAME="SoftSensorDescription.xml"
+SSM_LIB = libSSM.a
+SSMCORE_LIB=libSSMCore.a
# SoftSensorManager makefile path
-MAKE_01=${FD_SDK}/build/linux
-MAKE_02=${FD_SSMCORE}/build/linux
+MAKE_01=${FD_SSMCORE}/build/linux
+MAKE_02=${FD_SDK}/build/linux
MAKE_03=${FD_SAMPLEAPP}/linux
MAKE_04=${FD_SAMPLEAPP}/arduino
MAKE_05=${FD_SOFTSENSOR}/DiscomfortIndexSensor/build/linux
+MAKE_06=${FD_SOFTSENSOR}/IndoorTrajectorySensor/build/linux
-MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_03}
+MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_06} ${MAKE_03}
+#MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_03}