1// Copyright (c) 2012, Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30// This source file provides replacements for libc functions that we need. If 31// we call the libc functions directly we risk crashing in the dynamic linker 32// as it tries to resolve uncached PLT entries. 33 34#include "common/linux/linux_libc_support.h" 35 36#include <stddef.h> 37 38extern "C" { 39 40size_t my_strlen(const char* s) { 41 size_t len = 0; 42 while (*s++) len++; 43 return len; 44} 45 46int my_strcmp(const char* a, const char* b) { 47 for (;;) { 48 if (*a < *b) 49 return -1; 50 else if (*a > *b) 51 return 1; 52 else if (*a == 0) 53 return 0; 54 a++; 55 b++; 56 } 57} 58 59int my_strncmp(const char* a, const char* b, size_t len) { 60 for (size_t i = 0; i < len; ++i) { 61 if (*a < *b) 62 return -1; 63 else if (*a > *b) 64 return 1; 65 else if (*a == 0) 66 return 0; 67 a++; 68 b++; 69 } 70 71 return 0; 72} 73 74// Parse a non-negative integer. 75// result: (output) the resulting non-negative integer 76// s: a NUL terminated string 77// Return true iff successful. 78bool my_strtoui(int* result, const char* s) { 79 if (*s == 0) 80 return false; 81 int r = 0; 82 for (;; s++) { 83 if (*s == 0) 84 break; 85 const int old_r = r; 86 r *= 10; 87 if (*s < '0' || *s > '9') 88 return false; 89 r += *s - '0'; 90 if (r < old_r) 91 return false; 92 } 93 94 *result = r; 95 return true; 96} 97 98// Return the length of the given unsigned integer when expressed in base 10. 99unsigned my_uint_len(uintmax_t i) { 100 if (!i) 101 return 1; 102 103 int len = 0; 104 while (i) { 105 len++; 106 i /= 10; 107 } 108 109 return len; 110} 111 112// Convert an unsigned integer to a string 113// output: (output) the resulting string is written here. This buffer must be 114// large enough to hold the resulting string. Call |my_uint_len| to get the 115// required length. 116// i: the unsigned integer to serialise. 117// i_len: the length of the integer in base 10 (see |my_uint_len|). 118void my_uitos(char* output, uintmax_t i, unsigned i_len) { 119 for (unsigned index = i_len; index; --index, i /= 10) 120 output[index - 1] = '0' + (i % 10); 121} 122 123const char* my_strchr(const char* haystack, char needle) { 124 while (*haystack && *haystack != needle) 125 haystack++; 126 if (*haystack == needle) 127 return haystack; 128 return (const char*) 0; 129} 130 131const char* my_strrchr(const char* haystack, char needle) { 132 const char* ret = NULL; 133 while (*haystack) { 134 if (*haystack == needle) 135 ret = haystack; 136 haystack++; 137 } 138 return ret; 139} 140 141void* my_memchr(const void* src, int needle, size_t src_len) { 142 const unsigned char* p = (const unsigned char*)src; 143 const unsigned char* p_end = p + src_len; 144 for (; p < p_end; ++p) { 145 if (*p == needle) 146 return (void*)p; 147 } 148 return NULL; 149} 150 151// Read a hex value 152// result: (output) the resulting value 153// s: a string 154// Returns a pointer to the first invalid charactor. 155const char* my_read_hex_ptr(uintptr_t* result, const char* s) { 156 uintptr_t r = 0; 157 158 for (;; ++s) { 159 if (*s >= '0' && *s <= '9') { 160 r <<= 4; 161 r += *s - '0'; 162 } else if (*s >= 'a' && *s <= 'f') { 163 r <<= 4; 164 r += (*s - 'a') + 10; 165 } else if (*s >= 'A' && *s <= 'F') { 166 r <<= 4; 167 r += (*s - 'A') + 10; 168 } else { 169 break; 170 } 171 } 172 173 *result = r; 174 return s; 175} 176 177const char* my_read_decimal_ptr(uintptr_t* result, const char* s) { 178 uintptr_t r = 0; 179 180 for (;; ++s) { 181 if (*s >= '0' && *s <= '9') { 182 r *= 10; 183 r += *s - '0'; 184 } else { 185 break; 186 } 187 } 188 *result = r; 189 return s; 190} 191 192void my_memset(void* ip, char c, size_t len) { 193 char* p = (char *) ip; 194 while (len--) 195 *p++ = c; 196} 197 198size_t my_strlcpy(char* s1, const char* s2, size_t len) { 199 size_t pos1 = 0; 200 size_t pos2 = 0; 201 202 while (s2[pos2] != '\0') { 203 if (pos1 + 1 < len) { 204 s1[pos1] = s2[pos2]; 205 pos1++; 206 } 207 pos2++; 208 } 209 if (len > 0) 210 s1[pos1] = '\0'; 211 212 return pos2; 213} 214 215size_t my_strlcat(char* s1, const char* s2, size_t len) { 216 size_t pos1 = 0; 217 218 while (pos1 < len && s1[pos1] != '\0') 219 pos1++; 220 221 if (pos1 == len) 222 return pos1; 223 224 return pos1 + my_strlcpy(s1 + pos1, s2, len - pos1); 225} 226 227int my_isspace(int ch) { 228 // Matches the C locale. 229 const char spaces[] = " \t\f\n\r\t\v"; 230 for (size_t i = 0; i < sizeof(spaces); i++) { 231 if (ch == spaces[i]) 232 return 1; 233 } 234 return 0; 235} 236 237} // extern "C" 238