/* Copyright 2016 Samsung Electronics Co., Ltd.
 *
 * 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 "scl/string.h"

#if !defined(SCL_INSIDE_CPP) && defined(__cplusplus)
#	error .c file must be compiled only as C
#endif

extern scl_bool scl_strlen(char const *src, scl_size_t src_size, scl_size_t *len) {
	scl_bool ret;
	scl_size_t i;
	SCL_ASSERT(NULL != src);
	SCL_ASSERT(NULL != len);

	ret = (src_size > 0);
	*len = -1;
	if (ret) {
		--src_size;
		if (src_size > SCL_STRING_MAX_LEN) {
			src_size = SCL_STRING_MAX_LEN;
		}
		i = 0;
		while ((i < src_size) && (src[i] != '\0')) {
			++i;
		}
		ret = (src[i] == '\0');
		if (ret) {
			*len = i;
		}
	}
	return ret;
}

extern scl_bool scl_strcpy(char *dest, scl_size_t dest_size, char const *src) {
	scl_bool ret;
	scl_size_t i;
	SCL_ASSERT(NULL != dest);
	SCL_ASSERT(NULL != src);

	ret = (dest_size > 0);
	if (ret) {
		if (dest_size > SCL_STRING_MAX_LEN + 1) {
			dest_size = SCL_STRING_MAX_LEN + 1;
		}
		i = 0;
		while ((i < dest_size) && (src[i] != '\0')) {
			dest[i] = src[i];
			++i;
		}
		ret = i < dest_size;
		if (ret) {
			dest[i] = '\0';
		} else {
			dest[0] = '\0';
		}
	}
	return ret;
}

extern scl_bool scl_strncpy(char *dest, scl_size_t dest_size,
                            char const *src, scl_size_t max_n) {
	scl_bool ret;
	scl_size_t i;
	SCL_ASSERT(NULL != dest);
	SCL_ASSERT(NULL != src);

	ret = (dest_size > 0);
	if (ret) {
		if (dest_size > SCL_STRING_MAX_LEN + 1) {
			dest_size = SCL_STRING_MAX_LEN + 1;
		}
		i = 0;
		if (dest_size > max_n) {
			while ((i < max_n) && (src[i] != '\0')) {
				dest[i] = src[i];
				++i;
			}
			dest[i] = '\0';
		} else {
			while ((i < dest_size) && (src[i] != '\0')) {
				dest[i] = src[i];
				++i;
			}
			ret = i < dest_size;
			if (ret) {
				dest[i] = '\0';
			} else {
				dest[0] = '\0';
			}
		}
	}
	return ret;
}

extern scl_bool scl_strcat(char *dest, scl_size_t dest_size, char const *src) {
	scl_size_t len;
	SCL_ASSERT(NULL != src);
	return scl_strlen(dest, dest_size, &len)
	    && scl_strcpy(dest + len, dest_size - len, src);
}

extern scl_bool scl_strncat(char *dest, scl_size_t dest_size,
                            char const *src, scl_size_t max_n) {
	scl_size_t len;
	SCL_ASSERT(NULL != src);
	return scl_strlen (dest, dest_size, &len)
		&& scl_strncpy(dest + len, dest_size - len, src, max_n);
}

extern scl_bool scl_strmemcpy(char *dest, scl_size_t dest_size,
                              void const *src, scl_size_t src_size) {
	scl_size_t i;
	scl_bool ret;
	SCL_ASSERT(NULL != dest);
	SCL_ASSERT(NULL != src);
	ret = (src_size >= 0) && (src_size < dest_size)
		&&(src_size <= SCL_STRING_MAX_LEN);
	if (ret) {
		i = 0;
		while ((i < src_size) && (((char const *)src)[i] != '\0')) {
			++i;
		}
		ret = (i == src_size)
			&& scl_strncpy(dest, dest_size, (char const *)src, src_size / sizeof(char));
	}
	if (!ret && (dest_size > 0)) {
		dest[0] = '\0';
	}
	return ret;
}
