blob: ed681fda95a96442d99e301f4f08e6da403d763c [file] [log] [blame]
/**
*Licensed to the Apache Software Foundation (ASF) under one
*or more contributor license agreements. See the NOTICE file
*distributed with this work for additional information
*regarding copyright ownership. The ASF licenses this file
*to you 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.
*/
/*
* version_range.c
*
* \date Jul 12, 2010
* \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
* \copyright Apache License, Version 2.0
*/
#include <stdlib.h>
#include <string.h>
#include "version_range_private.h"
celix_status_t versionRange_createVersionRange(version_pt low, bool isLowInclusive,
version_pt high, bool isHighInclusive, version_range_pt *range) {
celix_status_t status = CELIX_SUCCESS;
*range = (version_range_pt) malloc(sizeof(**range));
if (!*range) {
status = CELIX_ENOMEM;
} else {
(*range)->low = low;
(*range)->isLowInclusive = isLowInclusive;
(*range)->high = high;
(*range)->isHighInclusive = isHighInclusive;
}
return status;
}
celix_status_t versionRange_destroy(version_range_pt range) {
if (range->high != NULL) {
version_destroy(range->high);
}
if (range->low != NULL) {
version_destroy(range->low);
}
range->high = NULL;
range->isHighInclusive = false;
range->low = NULL;
range->isLowInclusive = false;
free(range);
return CELIX_SUCCESS;
}
celix_status_t versionRange_createInfiniteVersionRange(version_range_pt *range) {
celix_status_t status;
version_pt version = NULL;
status = version_createEmptyVersion(&version);
if (status == CELIX_SUCCESS) {
status = versionRange_createVersionRange(version, true, NULL, true, range);
}
return status;
}
celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt version, bool *inRange) {
celix_status_t status;
if (versionRange->high == NULL) {
int cmp;
status = version_compareTo(version, versionRange->low, &cmp);
if (status == CELIX_SUCCESS) {
*inRange = (cmp >= 0);
}
} else if (versionRange->isLowInclusive && versionRange->isHighInclusive) {
int low, high;
status = version_compareTo(version, versionRange->low, &low);
if (status == CELIX_SUCCESS) {
status = version_compareTo(version, versionRange->high, &high);
if (status == CELIX_SUCCESS) {
*inRange = (low >= 0) && (high <= 0);
}
}
} else if (versionRange->isHighInclusive) {
int low, high;
status = version_compareTo(version, versionRange->low, &low);
if (status == CELIX_SUCCESS) {
status = version_compareTo(version, versionRange->high, &high);
if (status == CELIX_SUCCESS) {
*inRange = (low > 0) && (high <= 0);
}
}
} else if (versionRange->isLowInclusive) {
int low, high;
status = version_compareTo(version, versionRange->low, &low);
if (status == CELIX_SUCCESS) {
status = version_compareTo(version, versionRange->high, &high);
if (status == CELIX_SUCCESS) {
*inRange = (low >= 0) && (high < 0);
}
}
} else {
int low, high;
status = version_compareTo(version, versionRange->low, &low);
if (status == CELIX_SUCCESS) {
status = version_compareTo(version, versionRange->high, &high);
if (status == CELIX_SUCCESS) {
*inRange = (low > 0) && (high < 0);
}
}
}
return status;
}
celix_status_t versionRange_getLowVersion(version_range_pt versionRange, version_pt *lowVersion) {
celix_status_t status = CELIX_SUCCESS;
if (versionRange == NULL) {
status = CELIX_ILLEGAL_ARGUMENT;
}
else {
*lowVersion = versionRange->low;
}
return status;
}
celix_status_t versionRange_isLowInclusive(version_range_pt versionRange, bool *isLowInclusive) {
celix_status_t status = CELIX_SUCCESS;
if (versionRange == NULL) {
status = CELIX_ILLEGAL_ARGUMENT;
}
else {
*isLowInclusive = versionRange->isLowInclusive;
}
return status;
}
celix_status_t versionRange_getHighVersion(version_range_pt versionRange, version_pt *highVersion) {
celix_status_t status = CELIX_SUCCESS;
if (versionRange == NULL) {
status = CELIX_ILLEGAL_ARGUMENT;
}
else {
*highVersion = versionRange->high;
}
return status;
}
celix_status_t versionRange_isHighInclusive(version_range_pt versionRange, bool *isHighInclusive) {
celix_status_t status = CELIX_SUCCESS;
if (versionRange == NULL) {
status = CELIX_ILLEGAL_ARGUMENT;
}
else {
*isHighInclusive = versionRange->isHighInclusive;
}
return status;
}
celix_status_t versionRange_parse(const char * rangeStr, version_range_pt *range) {
celix_status_t status;
if (strchr(rangeStr, ',') != NULL) {
int vlowL = strcspn(rangeStr+1, ",");
char * vlow = (char *) malloc(sizeof(char) * (vlowL + 1));
if (!vlow) {
status = CELIX_ENOMEM;
} else {
int vhighL;
char * vhigh;
vlow = strncpy(vlow, rangeStr+1, vlowL);
vlow[vlowL] = '\0';
vhighL = strlen(rangeStr+1) - vlowL - 2;
vhigh = (char *) malloc(sizeof(char) * (vhighL+1));
if (!vhigh) {
status = CELIX_ENOMEM;
} else {
version_pt versionLow = NULL;
int rangeL = strlen(rangeStr);
char start = rangeStr[0];
char end = rangeStr[rangeL-1];
vhigh = strncpy(vhigh, rangeStr+vlowL+2, vhighL);
vhigh[vhighL] = '\0';
status = version_createVersionFromString(vlow, &versionLow);
if (status == CELIX_SUCCESS) {
version_pt versionHigh = NULL;
status = version_createVersionFromString(vhigh, &versionHigh);
if (status == CELIX_SUCCESS) {
status = versionRange_createVersionRange(
versionLow,
start == '[',
versionHigh,
end ==']',
range
);
}
}
free(vhigh);
}
free(vlow);
}
} else {
version_pt version = NULL;
status = version_createVersionFromString(rangeStr, &version);
if (status == CELIX_SUCCESS) {
status = versionRange_createVersionRange(version, true, NULL, false, range);
}
}
return status;
}