Index: uspace/lib/libc/generic/string.c
===================================================================
--- uspace/lib/libc/generic/string.c	(revision 171f9a1fe9f611d6f72a49a47ddb0eaefd93ccbd)
+++ uspace/lib/libc/generic/string.c	(revision f2b8cdc51775d0938392285312ca1ea65eca2f5b)
@@ -40,4 +40,5 @@
 #include <malloc.h>
 #include <errno.h>
+#include <align.h>
 #include <string.h>
 
@@ -193,4 +194,174 @@
 }
 
+/** Get size of string.
+ *
+ * Get the number of bytes which are used by the string @a str (excluding the
+ * NULL-terminator).
+ *
+ * @param str String to consider.
+ *
+ * @return Number of bytes used by the string
+ *
+ */
+size_t str_size(const char *str)
+{
+	size_t size = 0;
+	
+	while (*str++ != 0)
+		size++;
+	
+	return size;
+}
+
+/** Get size of wide string.
+ *
+ * Get the number of bytes which are used by the wide string @a str (excluding the
+ * NULL-terminator).
+ *
+ * @param str Wide string to consider.
+ *
+ * @return Number of bytes used by the wide string
+ *
+ */
+size_t wstr_size(const wchar_t *str)
+{
+	return (wstr_length(str) * sizeof(wchar_t));
+}
+
+/** Get size of string with length limit.
+ *
+ * Get the number of bytes which are used by up to @a max_len first
+ * characters in the string @a str. If @a max_len is greater than
+ * the length of @a str, the entire string is measured (excluding the
+ * NULL-terminator).
+ *
+ * @param str     String to consider.
+ * @param max_len Maximum number of characters to measure.
+ *
+ * @return Number of bytes used by the characters.
+ *
+ */
+size_t str_lsize(const char *str, count_t max_len)
+{
+	count_t len = 0;
+	size_t offset = 0;
+	
+	while (len < max_len) {
+		if (str_decode(str, &offset, STR_NO_LIMIT) == 0)
+			break;
+		
+		len++;
+	}
+	
+	return offset;
+}
+
+/** Get size of wide string with length limit.
+ *
+ * Get the number of bytes which are used by up to @a max_len first
+ * wide characters in the wide string @a str. If @a max_len is greater than
+ * the length of @a str, the entire wide string is measured (excluding the
+ * NULL-terminator).
+ *
+ * @param str     Wide string to consider.
+ * @param max_len Maximum number of wide characters to measure.
+ *
+ * @return Number of bytes used by the wide characters.
+ *
+ */
+size_t wstr_lsize(const wchar_t *str, count_t max_len)
+{
+	return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
+}
+
+/** Get number of characters in a string.
+ *
+ * @param str NULL-terminated string.
+ *
+ * @return Number of characters in string.
+ *
+ */
+count_t str_length(const char *str)
+{
+	count_t len = 0;
+	size_t offset = 0;
+	
+	while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
+		len++;
+	
+	return len;
+}
+
+/** Get number of characters in a wide string.
+ *
+ * @param str NULL-terminated wide string.
+ *
+ * @return Number of characters in @a str.
+ *
+ */
+count_t wstr_length(const wchar_t *wstr)
+{
+	count_t len = 0;
+	
+	while (*wstr++ != 0)
+		len++;
+	
+	return len;
+}
+
+/** Get number of characters in a string with size limit.
+ *
+ * @param str  NULL-terminated string.
+ * @param size Maximum number of bytes to consider.
+ *
+ * @return Number of characters in string.
+ *
+ */
+count_t str_nlength(const char *str, size_t size)
+{
+	count_t len = 0;
+	size_t offset = 0;
+	
+	while (str_decode(str, &offset, size) != 0)
+		len++;
+	
+	return len;
+}
+
+/** Get number of characters in a string with size limit.
+ *
+ * @param str  NULL-terminated string.
+ * @param size Maximum number of bytes to consider.
+ *
+ * @return Number of characters in string.
+ *
+ */
+count_t wstr_nlength(const wchar_t *str, size_t size)
+{
+	count_t len = 0;
+	count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
+	count_t offset = 0;
+	
+	while ((offset < limit) && (*str++ != 0)) {
+		len++;
+		offset += sizeof(wchar_t);
+	}
+	
+	return len;
+}
+
+/** Check whether character is plain ASCII.
+ *
+ * @return True if character is plain ASCII.
+ *
+ */
+bool ascii_check(wchar_t ch)
+{
+	if ((ch >= 0) && (ch <= 127))
+		return true;
+	
+	return false;
+}
+
 /** Check whether character is valid
  *
@@ -198,5 +369,5 @@
  *
  */
-bool chr_check(const wchar_t ch)
+bool chr_check(wchar_t ch)
 {
 	if ((ch >= 0) && (ch <= 1114111))
@@ -204,4 +375,234 @@
 	
 	return false;
+}
+
+/** Compare two NULL terminated strings.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings.
+ * The strings are considered equal iff they consist of the same
+ * characters on the minimum of their lengths.
+ *
+ * @param s1 First string to compare.
+ * @param s2 Second string to compare.
+ *
+ * @return 0 if the strings are equal, -1 if first is smaller,
+ *         1 if second smaller.
+ *
+ */
+int str_cmp(const char *s1, const char *s2)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+
+	while (true) {
+		c1 = str_decode(s1, &off1, STR_NO_LIMIT);
+		c2 = str_decode(s2, &off2, STR_NO_LIMIT);
+
+		if (c1 < c2)
+			return -1;
+		
+		if (c1 > c2)
+			return 1;
+
+		if (c1 == 0 || c2 == 0)
+			break;		
+	}
+
+	return 0;
+}
+
+/** Compare two NULL terminated strings with length limit.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings.
+ * The strings are considered equal iff they consist of the same
+ * characters on the minimum of their lengths and the length limit.
+ *
+ * @param s1      First string to compare.
+ * @param s2      Second string to compare.
+ * @param max_len Maximum number of characters to consider.
+ *
+ * @return 0 if the strings are equal, -1 if first is smaller,
+ *         1 if second smaller.
+ *
+ */
+int str_lcmp(const char *s1, const char *s2, count_t max_len)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+	
+	count_t len = 0;
+
+	while (true) {
+		if (len >= max_len)
+			break;
+
+		c1 = str_decode(s1, &off1, STR_NO_LIMIT);
+		c2 = str_decode(s2, &off2, STR_NO_LIMIT);
+
+		if (c1 < c2)
+			return -1;
+
+		if (c1 > c2)
+			return 1;
+
+		if (c1 == 0 || c2 == 0)
+			break;
+
+		++len;	
+	}
+
+	return 0;
+
+}
+
+/** Copy NULL-terminated string.
+ *
+ * Copy source string @a src to destination buffer @a dst.
+ * No more than @a size bytes are written. NULL-terminator is always
+ * written after the last succesfully copied character (i.e. if the
+ * destination buffer is has at least 1 byte, it will be always
+ * NULL-terminated).
+ *
+ * @param src   Source string.
+ * @param dst   Destination buffer.
+ * @param count Size of the destination buffer.
+ *
+ */
+void str_ncpy(char *dst, const char *src, size_t size)
+{
+	/* No space for the NULL-terminator in the buffer */
+	if (size == 0)
+		return;
+	
+	wchar_t ch;
+	size_t str_off = 0;
+	size_t dst_off = 0;
+	
+	while ((ch = str_decode(src, &str_off, STR_NO_LIMIT)) != 0) {
+		if (chr_encode(ch, dst, &dst_off, size) != EOK)
+			break;
+	}
+	
+	if (dst_off >= size)
+		dst[size - 1] = 0;
+	else
+		dst[dst_off] = 0;
+}
+
+/** Copy NULL-terminated wide string to string
+ *
+ * Copy source wide string @a src to destination buffer @a dst.
+ * No more than @a size bytes are written. NULL-terminator is always
+ * written after the last succesfully copied character (i.e. if the
+ * destination buffer is has at least 1 byte, it will be always
+ * NULL-terminated).
+ *
+ * @param src   Source wide string.
+ * @param dst   Destination buffer.
+ * @param count Size of the destination buffer.
+ *
+ */
+void wstr_nstr(char *dst, const wchar_t *src, size_t size)
+{
+	/* No space for the NULL-terminator in the buffer */
+	if (size == 0)
+		return;
+	
+	wchar_t ch;
+	count_t src_idx = 0;
+	size_t dst_off = 0;
+	
+	while ((ch = src[src_idx++]) != 0) {
+		if (chr_encode(ch, dst, &dst_off, size) != EOK)
+			break;
+	}
+	
+	if (dst_off >= size)
+		dst[size - 1] = 0;
+	else
+		dst[dst_off] = 0;
+}
+
+/** Find first occurence of character in string.
+ *
+ * @param str String to search.
+ * @param ch  Character to look for.
+ *
+ * @return Pointer to character in @a str or NULL if not found.
+ *
+ */
+const char *str_chr(const char *str, wchar_t ch)
+{
+	wchar_t acc;
+	size_t off = 0;
+	
+	while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
+		if (acc == ch)
+			return (str + off);
+	}
+	
+	return NULL;
+}
+
+/** Insert a wide character into a wide string.
+ *
+ * Insert a wide character into a wide string at position
+ * @a pos. The characters after the position are shifted.
+ *
+ * @param str     String to insert to.
+ * @param ch      Character to insert to.
+ * @param pos     Character index where to insert.
+ @ @param max_pos Characters in the buffer.
+ *
+ * @return True if the insertion was sucessful, false if the position
+ *         is out of bounds.
+ *
+ */
+bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
+{
+	count_t len = wstr_length(str);
+	
+	if ((pos > len) || (pos + 1 > max_pos))
+		return false;
+	
+	count_t i;
+	for (i = len; i + 1 > pos; i--)
+		str[i + 1] = str[i];
+	
+	str[pos] = ch;
+	
+	return true;
+}
+
+/** Remove a wide character from a wide string.
+ *
+ * Remove a wide character from a wide string at position
+ * @a pos. The characters after the position are shifted.
+ *
+ * @param str String to remove from.
+ * @param pos Character index to remove.
+ *
+ * @return True if the removal was sucessful, false if the position
+ *         is out of bounds.
+ *
+ */
+bool wstr_remove(wchar_t *str, count_t pos)
+{
+	count_t len = wstr_length(str);
+	
+	if (pos >= len)
+		return false;
+	
+	count_t i;
+	for (i = pos + 1; i <= len; i++)
+		str[i - 1] = str[i];
+	
+	return true;
 }
 
