1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_
6#define CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_
7
8#ifndef COMPILE_ASSERT
9// COMPILE_ASSERT macro borrowed from basictypes.h
10template <bool>
11struct CompileAssert {};
12#define COMPILE_ASSERT(expr, msg) \
13    typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
14#endif
15
16namespace mini_installer {
17
18// NOTE: Do not assume that these string functions support UTF encoding.
19// This is fine for the purposes of the mini_installer, but you have
20// been warned!
21
22// Formats a sequence of |bytes| as hex.  The |str| buffer must have room for
23// at least 2*|size| + 1.
24bool HexEncode(const void* bytes, size_t size, wchar_t* str, size_t str_size);
25
26// Counts the number of characters in the string up to a maximum of
27// alloc_size.  The highest return value from this function can therefore be
28// alloc_size - 1 since |alloc_size| includes the \0 terminator.
29size_t SafeStrLen(const wchar_t* str, size_t alloc_size);
30
31// Simple replacement for CRT string copy method that does not overflow.
32// Returns true if the source was copied successfully otherwise returns false.
33// Parameter src is assumed to be NULL terminated and the NULL character is
34// copied over to string dest.
35bool SafeStrCopy(wchar_t* dest, size_t dest_size, const wchar_t* src);
36
37// Simple replacement for CRT string copy method that does not overflow.
38// Returns true if the source was copied successfully otherwise returns false.
39// Parameter src is assumed to be NULL terminated and the NULL character is
40// copied over to string dest.  If the return value is false, the |dest|
41// string should be the same as it was before.
42bool SafeStrCat(wchar_t* dest, size_t dest_size, const wchar_t* src);
43
44// Function to check if a string (specified by str) ends with another string
45// (specified by end_str).
46bool StrEndsWith(const wchar_t* str, const wchar_t* end_str);
47
48// Function to check if a string (specified by str) starts with another string
49// (specified by start_str).
50bool StrStartsWith(const wchar_t* str, const wchar_t* start_str);
51
52// Case insensitive search of the first occurrence of |find| in |source|.
53const wchar_t* SearchStringI(const wchar_t* source, const wchar_t* find);
54
55// Searches for |tag| within |str|.  Returns true if |tag| is found and is
56// immediately followed by '-' or is at the end of the string.  If |position|
57// is non-NULL, the location of the tag is returned in |*position| on success.
58bool FindTagInStr(const wchar_t* str, const wchar_t* tag,
59                  const wchar_t** position);
60
61// Takes the path to file and returns a pointer to the filename component. For
62// example for input of c:\full\path\to\file.ext it returns pointer to file.ext.
63// It returns NULL if extension or path separator is not found.
64// |size| is the number of characters in |path| not including the string
65// terminator.
66wchar_t* GetNameFromPathExt(wchar_t* path, size_t size);
67
68// A string class that manages a fixed size buffer on the stack.
69// The methods in the class are based on the above string methods and the
70// class additionally is careful about proper buffer termination.
71template <size_t kCapacity>
72class StackString {
73 public:
74  StackString() {
75    COMPILE_ASSERT(kCapacity != 0, invalid_buffer_size);
76    buffer_[kCapacity] = L'\0';  // We always reserve 1 more than asked for.
77    clear();
78  }
79
80  // We do not expose a constructor that accepts a string pointer on purpose.
81  // We expect the caller to call assign() and handle failures.
82
83  // Returns the number of reserved characters in this buffer, _including_
84  // the reserved char for the terminator.
85  size_t capacity() const {
86    return kCapacity;
87  }
88
89  wchar_t* get() {
90    return buffer_;
91  }
92
93  bool assign(const wchar_t* str) {
94    return SafeStrCopy(buffer_, kCapacity, str);
95  }
96
97  bool append(const wchar_t* str) {
98    return SafeStrCat(buffer_, kCapacity, str);
99  }
100
101  void clear() {
102    buffer_[0] = L'\0';
103  }
104
105  size_t length() const {
106    return SafeStrLen(buffer_, kCapacity);
107  }
108
109  // Does a case insensitive search for a substring.
110  const wchar_t* findi(const wchar_t* find) const {
111    return SearchStringI(buffer_, find);
112  }
113
114  // Case insensitive string compare.
115  int comparei(const wchar_t* str) const {
116    return lstrcmpiW(buffer_, str);
117  }
118
119  // Case sensitive string compare.
120  int compare(const wchar_t* str) const {
121    return lstrcmpW(buffer_, str);
122  }
123
124  // Terminates the string at the specified location.
125  // Note: this method has no effect if this object's length is less than
126  // |location|.
127  bool truncate_at(size_t location) {
128    if (location >= kCapacity)
129      return false;
130    buffer_[location] = L'\0';
131    return true;
132  }
133
134 protected:
135  // We reserve 1 more than what is asked for as a safeguard against
136  // off-by-one errors.
137  wchar_t buffer_[kCapacity + 1];
138
139 private:
140  StackString(const StackString&);
141  StackString& operator=(const StackString&);
142};
143
144}  // namespace mini_installer
145
146#endif  // CHROME_INSTALLER_MINI_INSTALLER_MINI_STRING_H_
147