~linaro-toolchain-dev/cortex-strings/trunk

73 by Michael Hope
Added the C only routines from Newlib 1.20+20120605~git3af2fa7
1
/*
2
FUNCTION
3
	<<strlen>>---character string length
4
5
INDEX
6
	strlen
7
8
ANSI_SYNOPSIS
9
	#include <string.h>
10
	size_t strlen(const char *<[str]>);
11
12
TRAD_SYNOPSIS
13
	#include <string.h>
14
	size_t strlen(<[str]>)
15
	char *<[src]>;
16
17
DESCRIPTION
18
	The <<strlen>> function works out the length of the string
19
	starting at <<*<[str]>>> by counting chararacters until it
20
	reaches a <<NULL>> character.
21
22
RETURNS
23
	<<strlen>> returns the character count.
24
25
PORTABILITY
26
<<strlen>> is ANSI C.
27
28
<<strlen>> requires no supporting OS subroutines.
29
30
QUICKREF
31
	strlen ansi pure
32
*/
33
34
#include "shim.h"
35
#include <string.h>
36
#include <limits.h>
37
38
#define LBLOCKSIZE   (sizeof (long))
39
#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
40
41
#if LONG_MAX == 2147483647L
42
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
43
#else
44
#if LONG_MAX == 9223372036854775807L
45
/* Nonzero if X (a long int) contains a NULL byte. */
46
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
47
#else
48
#error long int is not a 32bit or 64bit type.
49
#endif
50
#endif
51
52
#ifndef DETECTNULL
53
#error long int is not a 32bit or 64bit byte
54
#endif
55
56
size_t
57
_DEFUN (strlen, (str),
58
	_CONST char *str)
59
{
60
  _CONST char *start = str;
61
62
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
63
  unsigned long *aligned_addr;
64
65
  /* Align the pointer, so we can search a word at a time.  */
66
  while (UNALIGNED (str))
67
    {
68
      if (!*str)
69
	return str - start;
70
      str++;
71
    }
72
73
  /* If the string is word-aligned, we can check for the presence of
74
     a null in each word-sized block.  */
75
  aligned_addr = (unsigned long *)str;
76
  while (!DETECTNULL (*aligned_addr))
77
    aligned_addr++;
78
79
  /* Once a null is detected, we check each byte in that block for a
80
     precise position of the null.  */
81
  str = (char *) aligned_addr;
82
83
#endif /* not PREFER_SIZE_OVER_SPEED */
84
85
  while (*str)
86
    str++;
87
  return str - start;
88
}