aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/algol/parc_URIPath.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/algol/parc_URIPath.c')
-rwxr-xr-xlibparc/parc/algol/parc_URIPath.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/libparc/parc/algol/parc_URIPath.c b/libparc/parc/algol/parc_URIPath.c
new file mode 100755
index 00000000..ef46dac9
--- /dev/null
+++ b/libparc/parc/algol/parc_URIPath.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * 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 <config.h>
+
+#include <LongBow/runtime.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include <parc/algol/parc_URIPath.h>
+
+#include <parc/algol/parc_URISegment.h>
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+
+struct parc_uri_path {
+ PARCArrayList *segments;
+};
+
+static void
+_parcURIPath_Finalize(PARCURIPath **pathPtr)
+{
+ assertNotNull(pathPtr, "Parameter must be a non-null pointer to a pointer to a PARCURIPath instance.");
+
+ PARCURIPath *path = *pathPtr;
+ if (path != NULL) {
+ parcArrayList_Destroy(&path->segments);
+ }
+}
+
+parcObject_ExtendPARCObject(PARCURIPath, _parcURIPath_Finalize, parcURIPath_Copy, parcURIPath_ToString, parcURIPath_Equals,
+ parcURIPath_Compare, NULL, NULL);
+
+PARCURIPath *
+parcURIPath_Create(void)
+{
+ PARCURIPath *result = parcObject_CreateInstance(PARCURIPath);
+ return result;
+}
+
+parcObject_ImplementAcquire(parcURIPath, PARCURIPath);
+
+parcObject_ImplementRelease(parcURIPath, PARCURIPath);
+
+PARCURIPath *
+parcURIPath_Append(PARCURIPath *path, const PARCURISegment *segment)
+{
+ parcArrayList_Add(path->segments, segment);
+ return path;
+}
+
+PARCURIPath *
+parcURIPath_Trim(PARCURIPath *path, size_t numberToRemove)
+{
+ size_t length = parcArrayList_Size(path->segments);
+ if (numberToRemove <= length) {
+ while (numberToRemove--) {
+ parcArrayList_RemoveAndDestroyAtIndex(path->segments, length - 1);
+ length--;
+ }
+ }
+ return path;
+}
+
+//PARCURIPath *
+//parcURIPath_Parse(const char *string, const char **pointer)
+//{
+// PARCURIPath *result = parcURIPath_Create();
+//
+// result->segments = parcArrayList_Create((void (*)(void **))parcURISegment_Release);
+// if (*string != 0) {
+// assertTrue(*string == '/', "Expected initial '/' character.");
+// *pointer = string;
+// while (**pointer != 0 && **pointer != '?' && **pointer != '#') {
+// PARCURISegment *segment = parcURISegment_Parse(++(*pointer), pointer);
+// parcURIPath_Append(result, segment);
+// }
+// }
+//
+// return result;
+//}
+
+PARCURIPath *
+parcURIPath_Parse(const char *string, const char **pointer)
+{
+ PARCURIPath *result = parcURIPath_Create();
+ result->segments = parcArrayList_Create((void (*)(void **))parcURISegment_Release);
+
+ if (*string != 0) {
+ if (*string != '/') {
+ parcURIPath_Release(&result);
+ return NULL;
+ }
+
+ *pointer = string;
+ while (**pointer != 0 && **pointer != '?' && **pointer != '#') {
+ PARCURISegment *segment = parcURISegment_Parse(++(*pointer), pointer);
+ parcURIPath_Append(result, segment);
+ }
+ }
+
+ return result;
+}
+
+bool
+parcURIPath_Equals(const PARCURIPath *pathA, const PARCURIPath *pathB)
+{
+ if (pathA == pathB) {
+ return true;
+ }
+ if (pathA == NULL || pathB == NULL) {
+ return false;
+ }
+
+ if (parcArrayList_Size(pathA->segments) == parcArrayList_Size(pathB->segments)) {
+ for (size_t i = 0; i < parcArrayList_Size(pathA->segments); i++) {
+ PARCURISegment *segmentA = parcArrayList_Get(pathA->segments, i);
+ PARCURISegment *segmentB = parcArrayList_Get(pathB->segments, i);
+ if (!parcURISegment_Equals(segmentA, segmentB)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+PARCURIPath *
+parcURIPath_Copy(const PARCURIPath *path)
+{
+ assertNotNull(path, "Parameter must be a non-null PARC_URIPath pointer.");
+
+ PARCURIPath *result = parcURIPath_Create();
+ result->segments = parcArrayList_Create((void (*)(void **))parcURISegment_Release);
+
+ size_t nSegments = parcURIPath_Count(path);
+
+ for (size_t i = 0; i < nSegments; i++) {
+ PARCURISegment *segment = parcURIPath_Get(path, i);
+ PARCURISegment *segmentCopy = parcURISegment_Clone(segment);
+ parcURIPath_Append(result, segmentCopy);
+ }
+
+ return result;
+}
+
+PARCURIPath *
+parcURIPath_ComposeValist(const PARCURIPath *basePath, va_list varargs)
+{
+ PARCURIPath *result = parcURIPath_Copy(basePath);
+
+ for (PARCURISegment *segment = va_arg(varargs, PARCURISegment *); segment != NULL; segment = va_arg(varargs, PARCURISegment *)) {
+ parcURIPath_Append(result, parcURISegment_Clone(segment));
+ }
+
+ return result;
+}
+
+PARCURIPath *
+parcURIPath_Compose(const PARCURIPath *basePath, ...)
+{
+ va_list arglist;
+ va_start(arglist, basePath);
+
+ PARCURIPath *result = parcURIPath_ComposeValist(basePath, arglist);
+ va_end(arglist);
+
+ return result;
+}
+
+bool
+parcURIPath_StartsWith(const PARCURIPath *base, const PARCURIPath *prefix)
+{
+ size_t prefixSegmentCount = parcURIPath_Count(prefix);
+ size_t baseSegmentCount = parcURIPath_Count(base);
+
+ if (baseSegmentCount < prefixSegmentCount) {
+ return false;
+ }
+
+ for (size_t i = 0; i < prefixSegmentCount; i++) {
+ PARCURISegment *baseSegment = parcURIPath_Get(base, i);
+ PARCURISegment *prefixSegment = parcURIPath_Get(prefix, i);
+ if (parcURISegment_Compare(baseSegment, prefixSegment) != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int
+parcURIPath_Compare(const PARCURIPath *pathA, const PARCURIPath *pathB)
+{
+ if (pathA == NULL) {
+ if (pathB == NULL) {
+ return 0;
+ }
+ return -1;
+ } else {
+ if (pathB == NULL) {
+ return +1;
+ }
+ }
+
+ ssize_t countDifference = parcURIPath_Count(pathA) - parcURIPath_Count(pathB);
+
+ if (countDifference != 0) {
+ return (countDifference > 0 ? 1 : (countDifference < 0) ? -1 : 0);
+ }
+
+ size_t nSegments = parcURIPath_Count(pathA);
+
+ for (size_t i = 0; i < nSegments; i++) {
+ PARCURISegment *segmentA = parcURIPath_Get(pathA, i);
+ PARCURISegment *segmentB = parcURIPath_Get(pathB, i);
+ int comparison = parcURISegment_Compare(segmentA, segmentB);
+ if (comparison != 0) {
+ return comparison;
+ }
+ }
+ return 0;
+}
+
+PARCURISegment *
+parcURIPath_Get(const PARCURIPath *path, size_t index)
+{
+ return (PARCURISegment *) parcArrayList_Get(path->segments, index);
+}
+
+size_t
+parcURIPath_Count(const PARCURIPath *path)
+{
+ size_t nSegments = parcArrayList_Size(path->segments);
+ return nSegments;
+}
+
+size_t
+parcURIPath_Length(const PARCURIPath *path)
+{
+ size_t result = 0;
+
+ size_t nSegments = parcURIPath_Count(path);
+
+ for (size_t i = 0; i < nSegments; i++) {
+ PARCURISegment *segment = parcURIPath_Get(path, i);
+ result += parcURISegment_Length(segment);
+ if (i < (nSegments - 1)) {
+ result++; // Include the size of the '/' separators.
+ }
+ }
+
+ return result;
+}
+
+PARCBufferComposer *
+parcURIPath_BuildString(const PARCURIPath *path, PARCBufferComposer *composer)
+{
+ size_t nSegments = parcArrayList_Size(path->segments);
+
+ for (size_t i = 0; i < nSegments && composer != NULL; i++) {
+ if (parcURISegment_BuildString(parcURIPath_Get(path, i), composer) == NULL) {
+ composer = NULL;
+ }
+ if (i < (nSegments - 1)) {
+ composer = parcBufferComposer_PutChar(composer, '/');
+ }
+ }
+
+ return composer;
+}
+
+char *
+parcURIPath_ToString(const PARCURIPath *path)
+{
+ char *result = NULL;
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ if (composer != NULL) {
+ if (parcURIPath_BuildString(path, composer) != NULL) {
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ }
+ parcBufferComposer_Release(&composer);
+ }
+
+ return result;
+}