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