do not edit — generated by btf.
git.druid.rocksindexdruid520kaboomsrc/user/string.nsc

src/user/string.nsc


/*
 * string.h coverage. lib.nsc used to also carry my_strlen/str_eq --
 * real duplicates of strlen/strcmp here, kept around only because
 * migrating every call site was never done. that migration has now
 * happened: every program under src/user/ that needs a string length
 * or comparison includes this file and calls strlen/strcmp/strncmp
 * directly. str_eq had zero real callers anywhere and was deleted
 * outright. my_strlen survives as a lib.nsc-internal helper only --
 * stdio.nsc's fputs still calls it, since giving stdio.nsc its own
 * string.nsh dependency would need a matching change to mk/bu.sh's
 * per-program ".nsh"-grep dependency resolution (stdio.nsc is a
 * shared library module, not a program bu.sh scans there), which is a
 * build-system change, not a userland one.
 */
 
include "lib.nsh";
include "mem.nsh";
 
global u64
strlen(ptr s)
{
	u64 i;
 
	i = 0;
	while(ptr_byte_at(s, i) != (u8)0)
	{
		i = i + (u64)1;
	}
	return i;
}
 
global ptr
strcpy(ptr dst, ptr src)
{
	u64 n;
 
	n = strlen(src);
	memcpy(dst, src, n + (u64)1); /* +1 copies the null terminator too */
	return dst;
}
 
/* real strncpy semantics, not "strcpy but capped": pads with nulls up
 * to n if src is shorter, and does NOT null-terminate at all if src
 * is n bytes or longer -- exactly as surprising as the real libc
 * function, kept that way since anything porting real code expects
 * this exact (mis)behavior. */
global ptr
strncpy(ptr dst, ptr src, u64 n)
{
	u64 i;
	u64 slen;
 
	slen = strlen(src);
	i = 0;
	while(i < n)
	{
		if(i < slen)
		{
			mem_byte_set(dst, i, ptr_byte_at(src, i));
		}
		else
		{
			mem_byte_set(dst, i, (u8)0);
		}
		i = i + (u64)1;
	}
	return dst;
}
 
global ptr
strcat(ptr dst, ptr src)
{
	u64 dlen;
	u64 slen;
 
	dlen = strlen(dst);
	slen = strlen(src);
	memcpy(dst + dlen, src, slen + (u64)1);
	return dst;
}
 
global i32
strcmp(ptr a, ptr b)
{
	u64 i;
	u8 ca;
	u8 cb;
 
	i = 0;
	while(1)
	{
		ca = ptr_byte_at(a, i);
		cb = ptr_byte_at(b, i);
		if(ca != cb)
		{
			if(ca < cb)
			{
				return -1;
			}
			return 1;
		}
		if(ca == (u8)0)
		{
			return 0;
		}
		i = i + (u64)1;
	}
	return 0;
}
 
global i32
strncmp(ptr a, ptr b, u64 n)
{
	u64 i;
	u8 ca;
	u8 cb;
 
	i = 0;
	while(i < n)
	{
		ca = ptr_byte_at(a, i);
		cb = ptr_byte_at(b, i);
		if(ca != cb)
		{
			if(ca < cb)
			{
				return -1;
			}
			return 1;
		}
		if(ca == (u8)0)
		{
			return 0;
		}
		i = i + (u64)1;
	}
	return 0;
}
 
global ptr
strchr(ptr s, u8 ch)
{
	u64 i;
	u8 c;
 
	i = 0;
	while(1)
	{
		c = ptr_byte_at(s, i);
		if(c == ch)
		{
			return s + i;
		}
		if(c == (u8)0)
		{
			return (ptr)0;
		}
		i = i + (u64)1;
	}
	return (ptr)0;
}
 
/* real strrchr semantics include ch==0 matching the terminator itself
 * (i.e. strrchr(s, 0) returns a pointer to the end of the string) --
 * scanning through the terminator's own position (i <= len, not <)
 * gets that for free instead of needing a special case. */
global ptr
strrchr(ptr s, u8 ch)
{
	u64 i;
	u64 len;
	ptr result;
 
	len = strlen(s);
	result = (ptr)0;
	i = 0;
	while(i <= len)
	{
		if(ptr_byte_at(s, i) == ch)
		{
			result = s + i;
		}
		i = i + (u64)1;
	}
	return result;
}
powered by btf.