gwnavruntime/base/stringutils.h Source File

stringutils.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 #pragma once
8 
10 #include <stdarg.h>
11 #include <stdio.h>
12 
13 namespace Kaim
14 {
15 
17 struct StringSpan
18 {
19  StringSpan() : ptr(nullptr), size(0) {}
20  StringSpan(const char* ptr_, size_t size_) : ptr(ptr_), size(size_) {}
21 
22  const char* begin() const { return ptr; }
23  const char* end() const { return ptr + size; }
24  const char* pastend() const { return ptr + size + 1; }
25 
26  const char* ptr;
27  size_t size; // "abc" length is 3
28 };
29 
32 {
33  StringSplitSpan(const char* ptr_, size_t size_, bool found_) : span(ptr_, size_), found(found_) {}
34 
35  const char* ptr() const { return span.ptr; }
36  size_t size() const { return span.size; }
37  const char* begin() const { return span.begin(); }
38  const char* end() const { return span.end(); }
39  const char* pastend() const { return span.pastend(); }
40 
41  StringSpan span;
42  bool found;
43 };
44 
47 inline StringSplitSpan StringSplitFirst(const char* ptr, const char* delimiters)
48 {
49  for (size_t idx = 0; ; ++idx)
50  {
51  char c = ptr[idx];
52  if (c == '\0')
53  return StringSplitSpan(ptr, idx, false);
54 
55  for (size_t d = 0; ; ++d)
56  {
57  char s = delimiters[d];
58  if (s == '\0')
59  break;
60 
61  if (c == s)
62  return StringSplitSpan(ptr, idx, true);
63  }
64  }
65 }
66 
67 
68 
69 enum class StringSplitIgnoreEmpty { No, Yes };
70 
84 template <typename F>
85 inline size_t StringSplit(const char* ptr, const char* delimiters, const F& callable, StringSplitIgnoreEmpty ignoreEmpty = StringSplitIgnoreEmpty::Yes)
86 {
87  size_t count = 0;
88  for (;;)
89  {
90  auto split = StringSplitFirst(ptr, delimiters);
91 
92  if (ignoreEmpty == StringSplitIgnoreEmpty::No || split.size() != 0)
93  {
94  callable(split.span);
95  ++count;
96  }
97 
98  if (split.found == false)
99  break;
100 
101  ptr = split.pastend();
102  }
103 
104  return count;
105 }
106 
108 inline size_t StringPrintV(char* buffer, size_t buffer_size, const char* format, va_list vlist)
109 {
110  // because vsnprintf is not supported by msvc prior to vc14 aka vs2015
111 #if defined(KY_CC_MSVC) && KY_CC_MSVC < 1900 // < vc14 aka vs2015
112  int length = -1;
113  if (buffer_size != 0)
114  length = _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, vlist);
115  if (length == -1)
116  length = _vscprintf(format, vlist);
117 #else
118  // http://en.cppreference.com/w/cpp/io/c/vfprintf
119  // returns the number of chars that would have been written if buffer_size was large enough (not including the terminating null character) or a negative value if an error occurred.
120  int length = vsnprintf(buffer, buffer_size, format, vlist);
121 #endif
122 
123  if (length < 0)
124  return 0;
125 
126  if (((size_t)length) >= buffer_size)
127  return buffer_size - 1;
128 
129  return (size_t)length;
130 }
131 
132 inline size_t StringPrint(char* buffer, size_t buffer_size, const char* format, ...)
133 {
134  va_list vlist;
135  va_start(vlist, format);
136  size_t length = StringPrintV(buffer, buffer_size, format, vlist);
137  va_end(vlist);
138  return length;
139 }
140 
141 template<size_t N>
142 inline size_t StringPrint(char (&buffer)[N], const char* format, ...)
143 {
144  va_list vlist;
145  va_start(vlist, format);
146  size_t length = StringPrintV(buffer, N, format, vlist);
147  va_end(vlist);
148  return length;
149 }
150 
152 template<int ByteSize>
153 struct StringFmt
154 {
155  StringFmt(const char* format, ...)
156  {
157  va_list args_list;
158  va_start(args_list, format);
159  length = StringPrintV(str, ByteSize, format, args_list);
160  va_end(args_list);
161  }
162 
163  StringSpan Span() const { return StringSpan(str, length); }
164 
165  char str[ByteSize];
166  size_t length; // "abc" length is 3
167 };
168 
169 
170 } // namespace Kaim
171 
size_t StringSplit(const char *ptr, const char *delimiters, const F &callable, StringSplitIgnoreEmpty ignoreEmpty=StringSplitIgnoreEmpty::Yes)
Calls callable(const StringSpan& span) for each substring separated by one of the delimiters...
Definition: stringutils.h:85
usage: MyLogFuncThatTakesCharPtr(StringFmt<32>("my_integer = %d", my_integer).str) ...
Definition: stringutils.h:153
size_t StringPrintV(char *buffer, size_t buffer_size, const char *format, va_list vlist)
Writes at most buffer_size chars, always put a null char, returns the number of chars written (not in...
Definition: stringutils.h:108
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
result of StringSplitFirst, StringSplit
Definition: stringutils.h:31
Non owning range of char.
Definition: stringutils.h:17
StringSplitSpan StringSplitFirst(const char *ptr, const char *delimiters)
returns {ptr, size, true} where ptr[size] == first delimiter found returns {ptr, size, false} where ptr[size] == null if no delimiter can be found
Definition: stringutils.h:47