//------------------------------------------------------------------------------
// ZCPU CRT sourcecode (for HL-ZASM compiler)         (C) 2011 by Black Phoenix
//
// String library. Contains functions to work with C strings (C89-compatible)
//------------------------------------------------------------------------------

#define NULL 0

//copies n bytes between two memory areas; if there is overlap, the behavior is undefined
void *memcpy(void *dest, void *src, float n) {
  preserve esi,edi;
  register float rem;

  esi = src;
  edi = dest;
  rem = n;
  while (rem) {
    register float count = rem;
    min count,8192;
    mcopy count;
    rem = rem - count;
  }
  return dest;
}

//copies n bytes between two memory areas; unlike with memcpy the areas may overlap
//void *memmove(void *dest, void *src, float n);
#define memmove memcpy

//returns a pointer to the first occurrence of c in the first n bytes of s, or NULL if not found
void* memchr(void *s, float c, float n) {
  register void *r = s;
  register float rem = n;

  while (rem) {
    if (*r == c) {
      return r;
    }
    ++r;
    --rem;
  }

  return NULL;
}

//compares the first n bytes of two memory areas
//int memcmp(const void *s1, const void *s2, float n);
#define memcmp strcmp

//overwrites a memory area with n copies of c
void* memset(void *ptr, float c, float n) {
  register void *p = ptr;
  register float rem = n;
  register float ch = c;

  while (rem) {
    *p++ = ch;
    --rem;
  }

  return ptr;
}

//appends the string src to dest
char* strcat(char *src, *dest) {
  register char *srcptr, *destptr;

  srcptr = src;
  while (*++srcptr) ;

  destptr = dest;
  while (*srcptr++ = *destptr++) ;
  return src;
}

//appends at most n bytes of the string src to dest
char* strncat(char *src, *dest, float n) {
  register char *srcptr, *destptr;
  register float i;

  srcptr = src;
  srcptr--;
  while (*++srcptr) ;

  destptr = dest;
  i = n;
  while (i--) {
    if (*srcptr++ = *destptr++) continue;
  }
  *srcptr = 0;
  return src;
}

//locates character c in a string, searching from the beginning
char* strchr(char *str, c) {
  register char *strptr, ch;
  strptr = str;
  ch = c;
  while(*strptr) {
    if (*strptr == ch) return strptr;
    ++strptr;
  }
  return 0;
}

//locates character c in a string, searching from the end
char* strrchr(char *str, c) {
  register char *strptr, ch;
  register char *findptr;

  findptr = 0;
  strptr = str;
  ch = c;
  while (*strptr) {
    if (*strptr == ch) findptr = strptr;
    ++strptr;
  }
  return findptr;
}

//compares two strings lexicographically
float strcmp(char *src, *dest) {
  register char *srcptr, *destptr;

  srcptr = src;
  destptr = dest;
  while (*srcptr == *destptr) {
    if (*srcptr == 0) return 0;
    ++srcptr; ++destptr;
  }
  return (*srcptr - *destptr);
}

//compares up to the first n bytes of two strings lexicographically
float strncmp(char *src, *dest, float n) {
  register char *srcptr, *destptr;
  register float i;

  srcptr = src;
  destptr = dest;
  i = n;

  while (i && (*srcptr == *destptr)) {
    if (*srcptr == 0) return 0;
    ++srcptr; ++destptr; --i;
  }
  if (i) return (*srcptr - *destptr);
  return 0;
}

//copies a string from one location to another
char* strcpy(char *dest, *src) {
  register char *srcptr, *destptr;

  destptr = dest;
  srcptr = src;
  while (*destptr++ = *srcptr++) ;
  return dest;
}


//write exactly n bytes to dest, copying from src or add 0's
char* strncpy(char *dest, *src, float n) {
  register char *srcptr, *destptr;
  register float i;

  destptr = dest;
  srcptr = src;
  i = n;

  while (i-- > 0) {
    if (*destptr++ = *srcptr++) continue;
    while (i-- > 0) *destptr++ = 0;
  }
  *destptr = 0;
  return dest;
}

//returns the string representation of an error number e.g. errno
//char *strerror(int);

//finds the length of a C string
float strlen(char* str) {
  register char* strptr;
  register float n;

  strptr = str;
  n = 0;
  while (*strptr++) n++;
  return n;
}

//determines the length of the maximal initial substring consisting entirely of characters in accept
float strspn(char *str, *accept) {
  register char *s = str;
  register char *p = accept;

  while (*p) {
    if (*p++ == *s) {
      ++s;
      p = accept;
    }
  }
  return s - str;
}

//determines the length of the maximal initial substring consisting entirely of characters not in reject
float strcspn(char *str, char *reject) {
  register char *s, *p;

  for (s=str; *s; s++) {
    for (p=reject; *p; p++) {
      if (*p == *s) goto done;
    }
  }
  done:
  return s - str;
}

//finds the first occurrence of any character in accept
char* strpbrk(char *str, char *accept) {
  register char *s;
  register char *p;

  for (s=str; *s; s++) {
    for (p=accept; *p; p++) {
      if (*p == *s) return s;
    }
  }
  return NULL;
}

//finds the first occurrence of the string "needle" in the longer string "haystack"
char *strstr(char *haystack, char *needle) {
  register char *s = haystack;
  register char *p = needle;

  while (1) {
    if (!*p) {
      return haystack;
    }
    if (*p == *s) {
      ++p;
      ++s;
    } else {
      p = needle;
      if (!*s) {
        return NULL;
      }
      s = ++haystack;
    }
  }
}

//parses a string into a sequence of tokens; non-thread safe in the spec, non-reentrant
//char *strtok(char *, const char * delim);

//transforms src into a collating form, such that the numerical sort order of the transformed string is equivalent to the collating order of src
//float strxfrm(char *dest, const char *src, float n);
