/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * MODULE NOTES: * @update gess7/30/98 * * Much as I hate to do it, we were using string compares wrong. * Often, programmers call functions like strcmp(s1,s2), and pass * one or more null strings. Rather than blow up on these, I've * added quick checks to ensure that cases like this don't cause * us to fail. * * In general, if you pass a null into any of these string compare * routines, we simply return 0. */ #include "nsCRT.h" #include "nsDebug.h" //---------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// // My lovely strtok routine #define IS_DELIM(m, c) ((m)[(c) >> 3] & (1 << ((c) & 7))) #define SET_DELIM(m, c) ((m)[(c) >> 3] |= (1 << ((c) & 7))) #define DELIM_TABLE_SIZE 32 char* nsCRT::strtok(char* aString, const char* aDelims, char** aNewStr) { NS_ASSERTION(aString, "Unlike regular strtok, the first argument cannot be null."); char delimTable[DELIM_TABLE_SIZE]; uint32_t i; char* result; char* str = aString; for (i = 0; i < DELIM_TABLE_SIZE; ++i) { delimTable[i] = '\0'; } for (i = 0; aDelims[i]; i++) { SET_DELIM(delimTable, static_cast<uint8_t>(aDelims[i])); } NS_ASSERTION(aDelims[i] == '\0', "too many delimiters"); // skip to beginning while (*str && IS_DELIM(delimTable, static_cast<uint8_t>(*str))) { str++; } result = str; // fix up the end of the token while (*str) { if (IS_DELIM(delimTable, static_cast<uint8_t>(*str))) { *str++ = '\0'; break; } str++; } *aNewStr = str; return str == result ? nullptr : result; } //////////////////////////////////////////////////////////////////////////////// /** * Compare unichar string ptrs, stopping at the 1st null * NOTE: If both are null, we return 0. * NOTE: We terminate the search upon encountering a nullptr * * @update gess 11/10/99 * @param s1 and s2 both point to unichar strings * @return 0 if they match, -1 if s1<s2; 1 if s1>s2 */ int32_t nsCRT::strcmp(const char16_t* aStr1, const char16_t* aStr2) { if (aStr1 && aStr2) { for (;;) { char16_t c1 = *aStr1++; char16_t c2 = *aStr2++; if (c1 != c2) { if (c1 < c2) { return -1; } return 1; } if (c1 == 0 || c2 == 0) { break; } } } else { if (aStr1) { // aStr2 must have been null return -1; } if (aStr2) { // aStr1 must have been null return 1; } } return 0; } /** * Compare unichar string ptrs, stopping at the 1st null or nth char. * NOTE: If either is null, we return 0. * NOTE: We DO NOT terminate the search upon encountering nullptr's before N * * @update gess 11/10/99 * @param s1 and s2 both point to unichar strings * @return 0 if they match, -1 if s1<s2; 1 if s1>s2 */ int32_t nsCRT::strncmp(const char16_t* aStr1, const char16_t* aStr2, uint32_t aNum) { if (aStr1 && aStr2) { if (aNum != 0) { do { char16_t c1 = *aStr1++; char16_t c2 = *aStr2++; if (c1 != c2) { if (c1 < c2) { return -1; } return 1; } } while (--aNum != 0); } } return 0; } const char* nsCRT::memmem(const char* aHaystack, uint32_t aHaystackLen, const char* aNeedle, uint32_t aNeedleLen) { // Sanity checking if (!(aHaystack && aNeedle && aHaystackLen && aNeedleLen && aNeedleLen <= aHaystackLen)) { return nullptr; } #ifdef HAVE_MEMMEM return (const char*)::memmem(aHaystack, aHaystackLen, aNeedle, aNeedleLen); #else // No memmem means we need to roll our own. This isn't really optimized // for performance ... if that becomes an issue we can take some inspiration // from the js string compare code in jsstr.cpp for (uint32_t i = 0; i < aHaystackLen - aNeedleLen; i++) { if (!memcmp(aHaystack + i, aNeedle, aNeedleLen)) { return aHaystack + i; } } #endif return nullptr; } // This should use NSPR but NSPR isn't exporting its PR_strtoll function // Until then... int64_t nsCRT::atoll(const char* aStr) { if (!aStr) { return 0; } int64_t ll = 0; while (*aStr && *aStr >= '0' && *aStr <= '9') { ll *= 10; ll += *aStr - '0'; aStr++; } return ll; }