mini_string.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef COMPILE_ASSERT
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// COMPILE_ASSERT macro borrowed from basictypes.h
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <bool>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CompileAssert {};
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COMPILE_ASSERT(expr, msg) \
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mini_installer {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: Do not assume that these string functions support UTF encoding.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is fine for the purposes of the mini_installer, but you have
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// been warned!
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Formats a sequence of |bytes| as hex.  The |str| buffer must have room for
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at least 2*|size| + 1.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HexEncode(const void* bytes, size_t size, wchar_t* str, size_t str_size);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Counts the number of characters in the string up to a maximum of
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// alloc_size.  The highest return value from this function can therefore be
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// alloc_size - 1 since |alloc_size| includes the \0 terminator.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SafeStrLen(const wchar_t* str, size_t alloc_size);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple replacement for CRT string copy method that does not overflow.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the source was copied successfully otherwise returns false.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameter src is assumed to be NULL terminated and the NULL character is
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copied over to string dest.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SafeStrCopy(wchar_t* dest, size_t dest_size, const wchar_t* src);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple replacement for CRT string copy method that does not overflow.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the source was copied successfully otherwise returns false.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameter src is assumed to be NULL terminated and the NULL character is
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copied over to string dest.  If the return value is false, the |dest|
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string should be the same as it was before.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SafeStrCat(wchar_t* dest, size_t dest_size, const wchar_t* src);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Function to check if a string (specified by str) ends with another string
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (specified by end_str).
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StrEndsWith(const wchar_t* str, const wchar_t* end_str);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Function to check if a string (specified by str) starts with another string
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (specified by start_str).
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StrStartsWith(const wchar_t* str, const wchar_t* start_str);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Case insensitive search of the first occurrence of |find| in |source|.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t* SearchStringI(const wchar_t* source, const wchar_t* find);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Searches for |tag| within |str|.  Returns true if |tag| is found and is
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// immediately followed by '-' or is at the end of the string.  If |position|
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is non-NULL, the location of the tag is returned in |*position| on success.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindTagInStr(const wchar_t* str, const wchar_t* tag,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const wchar_t** position);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Takes the path to file and returns a pointer to the filename component. For
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// example for input of c:\full\path\to\file.ext it returns pointer to file.ext.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It returns NULL if extension or path separator is not found.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |size| is the number of characters in |path| not including the string
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// terminator.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wchar_t* GetNameFromPathExt(wchar_t* path, size_t size);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A string class that manages a fixed size buffer on the stack.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The methods in the class are based on the above string methods and the
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// class additionally is careful about proper buffer termination.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <size_t kCapacity>
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StackString {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StackString() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COMPILE_ASSERT(kCapacity != 0, invalid_buffer_size);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_[kCapacity] = L'\0';  // We always reserve 1 more than asked for.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clear();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not expose a constructor that accepts a string pointer on purpose.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We expect the caller to call assign() and handle failures.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the number of reserved characters in this buffer, _including_
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the reserved char for the terminator.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t capacity() const {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kCapacity;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t* get() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer_;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool assign(const wchar_t* str) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SafeStrCopy(buffer_, kCapacity, str);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool append(const wchar_t* str) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SafeStrCat(buffer_, kCapacity, str);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void clear() {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_[0] = L'\0';
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t length() const {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SafeStrLen(buffer_, kCapacity);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does a case insensitive search for a substring.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* findi(const wchar_t* find) const {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SearchStringI(buffer_, find);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Case insensitive string compare.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int comparei(const wchar_t* str) const {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return lstrcmpiW(buffer_, str);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Case sensitive string compare.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int compare(const wchar_t* str) const {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return lstrcmpW(buffer_, str);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Terminates the string at the specified location.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this method has no effect if this object's length is less than
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |location|.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool truncate_at(size_t location) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (location >= kCapacity)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_[location] = L'\0';
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We reserve 1 more than what is asked for as a safeguard against
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // off-by-one errors.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t buffer_[kCapacity + 1];
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StackString(const StackString&);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StackString& operator=(const StackString&);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace mini_installer
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_
147