TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Util.cpp File Reference
#include "Util.h"
#include "Common.h"
#include "CompilerDefs.h"
#include "utf8.h"
#include "Errors.h"
#include <stdarg.h>
#include <boost/algorithm/string/case_conv.hpp>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+ Include dependency graph for Util.cpp:

Typedefs

typedef wchar_t const *constwstrlist
 

Functions

void stripLineInvisibleChars (std::string &str)
 
std::string secsToTimeString (uint64 timeInSecs, bool shortText, bool hoursOnly)
 
int64 MoneyStringToMoney (const std::string &moneyString)
 
uint32 TimeStringToSecs (const std::string &timestring)
 
std::string TimeToTimestampStr (time_t t)
 
bool IsIPAddress (char const *ipaddress)
 Check if the string is a valid ip address representation. More...
 
uint32 CreatePIDFile (std::string const &filename)
 create PID file More...
 
uint32 GetPID ()
 
size_t utf8length (std::string &utf8str)
 
void utf8truncate (std::string &utf8str, size_t len)
 
bool Utf8toWStr (char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
 
bool Utf8toWStr (const std::string &utf8str, std::wstring &wstr)
 
bool WStrToUtf8 (wchar_t *wstr, size_t size, std::string &utf8str)
 
bool WStrToUtf8 (std::wstring const &wstr, std::string &utf8str)
 
std::wstring GetMainPartOfName (std::wstring const &wname, uint32 declension)
 
bool utf8ToConsole (const std::string &utf8str, std::string &conStr)
 
bool consoleToUtf8 (const std::string &conStr, std::string &utf8str)
 
bool Utf8FitTo (const std::string &str, std::wstring const &search)
 
void utf8printf (FILE *out, const char *str,...)
 
void vutf8printf (FILE *out, const char *str, va_list *ap)
 
bool Utf8ToUpperOnlyLatin (std::string &utf8String)
 
std::string ByteArrayToHexStr (uint8 const *bytes, uint32 arrayLen, bool reverse)
 
void HexStrToByteArray (std::string const &str, uint8 *out, bool reverse)
 
bool StringToBool (std::string const &str)
 

Typedef Documentation

typedef wchar_t const* const* wstrlist

Function Documentation

std::string ByteArrayToHexStr ( uint8 const bytes,
uint32  arrayLen,
bool  reverse 
)
510 {
511  int32 init = 0;
512  int32 end = arrayLen;
513  int8 op = 1;
514 
515  if (reverse)
516  {
517  init = arrayLen - 1;
518  end = -1;
519  op = -1;
520  }
521 
522  std::ostringstream ss;
523  for (int32 i = init; i != end; i += op)
524  {
525  char buffer[4];
526  sprintf(buffer, "%02X", bytes[i]);
527  ss << buffer;
528  }
529 
530  return ss.str();
531 }
int8_t int8
Definition: Define.h:148
std::string sprintf(CStringRef format, ArgList args)
Definition: format.h:3096
int32_t int32
Definition: Define.h:146

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool consoleToUtf8 ( const std::string &  conStr,
std::string &  utf8str 
)
439 {
440 #if PLATFORM == PLATFORM_WINDOWS
441  std::wstring wstr;
442  wstr.resize(conStr.size());
443  OemToCharBuffW(&conStr[0], &wstr[0], uint32(conStr.size()));
444 
445  return WStrToUtf8(wstr, utf8str);
446 #else
447  // not implemented yet
448  utf8str = conStr;
449  return true;
450 #endif
451 }
bool WStrToUtf8(wchar_t *wstr, size_t size, std::string &utf8str)
Definition: Util.cpp:328
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

uint32 CreatePIDFile ( std::string const filename)

create PID file

223 {
224  FILE* pid_file = fopen(filename.c_str(), "w");
225  if (pid_file == NULL)
226  return 0;
227 
228  uint32 pid = GetPID();
229 
230  fprintf(pid_file, "%u", pid);
231  fclose(pid_file);
232 
233  return pid;
234 }
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args)
arena_t NULL
Definition: jemalloc_internal.h:624
uint32_t uint32
Definition: Define.h:150
uint32 GetPID()
Definition: Util.cpp:236

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::wstring GetMainPartOfName ( std::wstring const wname,
uint32  declension 
)
377 {
378  // supported only Cyrillic cases
379  if (wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5)
380  return wname;
381 
382  // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
383 
384  static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430), wchar_t(0x0000)};
385  static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E), wchar_t(0x0000)};
386  static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F), wchar_t(0x0000)};
387  static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435), wchar_t(0x0000)};
388  static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438), wchar_t(0x0000)};
389  static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B), wchar_t(0x0000)};
390  static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443), wchar_t(0x0000)};
391  static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E), wchar_t(0x0000)};
392  static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E), wchar_t(0x0439), wchar_t(0x0000)};
393  static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435), wchar_t(0x0439), wchar_t(0x0000)};
394  static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451), wchar_t(0x0439), wchar_t(0x0000)};
395  static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E), wchar_t(0x043C), wchar_t(0x0000)};
396  static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451), wchar_t(0x043C), wchar_t(0x0000)};
397  static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435), wchar_t(0x043C), wchar_t(0x0000)};
398  static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C), wchar_t(0x0000)};
399  static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439), wchar_t(0x0000)};
400 
401  static wchar_t const* const dropEnds[6][8] = {
402  { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL },
403  { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL },
404  { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL },
405  { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL },
406  { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL },
407  { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL }
408  };
409 
410  for (wchar_t const* const* itr = &dropEnds[declension][0]; *itr; ++itr)
411  {
412  size_t len = size_t((*itr)[-1]); // get length from string size field
413 
414  if (wname.substr(wname.size()-len, len)==*itr)
415  return wname.substr(0, wname.size()-len);
416  }
417 
418  return wname;
419 }
bool isCyrillicCharacter(wchar_t wchar)
Definition: Util.h:164
arena_t NULL
Definition: jemalloc_internal.h:624

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

uint32 GetPID ( )
237 {
238 #ifdef _WIN32
239  DWORD pid = GetCurrentProcessId();
240 #else
241  pid_t pid = getpid();
242 #endif
243 
244  return uint32(pid);
245 }
unsigned int DWORD
Definition: CascPort.h:139
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the caller graph for this function:

void HexStrToByteArray ( std::string const str,
uint8 out,
bool  reverse 
)
534 {
535  // string must have even number of characters
536  if (str.length() & 1)
537  return;
538 
539  int32 init = 0;
540  int32 end = int32(str.length());
541  int8 op = 1;
542 
543  if (reverse)
544  {
545  init = int32(str.length() - 2);
546  end = -2;
547  op = -1;
548  }
549 
550  uint32 j = 0;
551  for (int32 i = init; i != end; i += 2 * op)
552  {
553  char buffer[3] = { str[i], str[i + 1], '\0' };
554  out[j++] = uint8(strtoul(buffer, NULL, 16));
555  }
556 }
int8_t int8
Definition: Define.h:148
arena_t NULL
Definition: jemalloc_internal.h:624
int32_t int32
Definition: Define.h:146
uint32_t uint32
Definition: Define.h:150
uint8_t uint8
Definition: g3dmath.h:164
int32_t int32
Definition: g3dmath.h:167

+ Here is the caller graph for this function:

bool IsIPAddress ( char const ipaddress)

Check if the string is a valid ip address representation.

212 {
213  if (!ipaddress)
214  return false;
215 
216  // Let the big boys do it.
217  // Drawback: all valid ip address formats are recognized e.g.: 12.23, 121234, 0xABCD)
218  return inet_addr(ipaddress) != INADDR_NONE;
219 }

+ Here is the caller graph for this function:

int64 MoneyStringToMoney ( const std::string &  moneyString)
133 {
134  int64 money = 0;
135 
136  if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
137  std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
138  std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
139  return 0; // Bad format
140 
141  Tokenizer tokens(moneyString, ' ');
142  for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
143  {
144  std::string tokenString(*itr);
145  size_t gCount = std::count(tokenString.begin(), tokenString.end(), 'g');
146  size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's');
147  size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c');
148  if (gCount + sCount + cCount != 1)
149  return 0;
150 
151  uint64 amount = atoull(*itr);
152  if (gCount == 1)
153  money += amount * 100 * 100;
154  else if (sCount == 1)
155  money += amount * 100;
156  else if (cCount == 1)
157  money += amount;
158  }
159 
160  return money;
161 }
unsigned long long atoull(char const *str)
Definition: Common.h:91
int64_t int64
Definition: Define.h:145
Definition: Util.h:45
StorageType::const_iterator const_iterator
Definition: Util.h:52
uint64_t uint64
Definition: Define.h:149

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::string secsToTimeString ( uint64  timeInSecs,
bool  shortText,
bool  hoursOnly 
)
110 {
111  uint64 secs = timeInSecs % MINUTE;
112  uint64 minutes = timeInSecs % HOUR / MINUTE;
113  uint64 hours = timeInSecs % DAY / HOUR;
114  uint64 days = timeInSecs / DAY;
115 
116  std::ostringstream ss;
117  if (days)
118  ss << days << (shortText ? "d" : " Day(s) ");
119  if (hours || hoursOnly)
120  ss << hours << (shortText ? "h" : " Hour(s) ");
121  if (!hoursOnly)
122  {
123  if (minutes)
124  ss << minutes << (shortText ? "m" : " Minute(s) ");
125  if (secs || (!days && !hours && !minutes) )
126  ss << secs << (shortText ? "s" : " Second(s).");
127  }
128 
129  return ss.str();
130 }
Definition: Common.h:98
Definition: Common.h:97
float minutes()
Definition: units.h:102
Definition: Common.h:99
uint64_t uint64
Definition: Define.h:149
float hours()
Definition: units.h:107
float days()
Definition: units.h:112

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool StringToBool ( std::string const str)
559 {
560  std::string lowerStr = boost::algorithm::to_lower_copy(str);
561  return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes";
562 }

+ Here is the caller graph for this function:

void stripLineInvisibleChars ( std::string &  str)
68 {
69  static std::string const invChars = " \t\7\n";
70 
71  size_t wpos = 0;
72 
73  bool space = false;
74  for (size_t pos = 0; pos < str.size(); ++pos)
75  {
76  if (invChars.find(str[pos])!=std::string::npos)
77  {
78  if (!space)
79  {
80  str[wpos++] = ' ';
81  space = true;
82  }
83  }
84  else
85  {
86  if (wpos!=pos)
87  str[wpos++] = str[pos];
88  else
89  ++wpos;
90  space = false;
91  }
92  }
93 
94  if (wpos < str.size())
95  str.erase(wpos, str.size());
96  if (str.find("|TInterface")!=std::string::npos)
97  str.clear();
98 
99 }

+ Here is the caller graph for this function:

uint32 TimeStringToSecs ( const std::string &  timestring)
164 {
165  uint32 secs = 0;
166  uint32 buffer = 0;
167  uint32 multiplier = 0;
168 
169  for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); ++itr)
170  {
171  if (isdigit(*itr))
172  {
173  buffer*=10;
174  buffer+= (*itr)-'0';
175  }
176  else
177  {
178  switch (*itr)
179  {
180  case 'd': multiplier = DAY; break;
181  case 'h': multiplier = HOUR; break;
182  case 'm': multiplier = MINUTE; break;
183  case 's': multiplier = 1; break;
184  default : return 0; //bad format
185  }
186  buffer*=multiplier;
187  secs+=buffer;
188  buffer=0;
189  }
190  }
191 
192  return secs;
193 }
Definition: Common.h:98
Definition: Common.h:97
Definition: Common.h:99
uint32_t uint32
Definition: Define.h:150

+ Here is the caller graph for this function:

std::string TimeToTimestampStr ( time_t  t)
196 {
197  tm aTm;
198  localtime_r(&t, &aTm);
199  // YYYY year
200  // MM month (2 digits 01-12)
201  // DD day (2 digits 01-31)
202  // HH hour (2 digits 00-23)
203  // MM minutes (2 digits 00-59)
204  // SS seconds (2 digits 00-59)
205  char buf[20];
206  snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
207  return std::string(buf);
208 }
#define snprintf
Definition: Common.h:76
TC_COMMON_API struct tm * localtime_r(const time_t *time, struct tm *result)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool Utf8FitTo ( const std::string &  str,
std::wstring const search 
)
454 {
455  std::wstring temp;
456 
457  if (!Utf8toWStr(str, temp))
458  return false;
459 
460  // converting to lower case
461  wstrToLower(temp);
462 
463  if (temp.find(search) == std::wstring::npos)
464  return false;
465 
466  return true;
467 }
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:281
void wstrToLower(std::wstring &str)
Definition: Util.h:306

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t utf8length ( std::string &  utf8str)
248 {
249  try
250  {
251  return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
252  }
253  catch(std::exception)
254  {
255  utf8str.clear();
256  return 0;
257  }
258 }
std::iterator_traits< octet_iterator >::difference_type distance(octet_iterator first, octet_iterator last)
Definition: checked.h:198

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void utf8printf ( FILE *  out,
const char *  str,
  ... 
)
470 {
471  va_list ap;
472  va_start(ap, str);
473  vutf8printf(out, str, &ap);
474  va_end(ap);
475 }
void vutf8printf(FILE *out, const char *str, va_list *ap)
Definition: Util.cpp:477

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool utf8ToConsole ( const std::string &  utf8str,
std::string &  conStr 
)
422 {
423 #if PLATFORM == PLATFORM_WINDOWS
424  std::wstring wstr;
425  if (!Utf8toWStr(utf8str, wstr))
426  return false;
427 
428  conStr.resize(wstr.size());
429  CharToOemBuffW(&wstr[0], &conStr[0], uint32(wstr.size()));
430 #else
431  // not implemented yet
432  conStr = utf8str;
433 #endif
434 
435  return true;
436 }
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:281
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the call graph for this function:

bool Utf8ToUpperOnlyLatin ( std::string &  utf8String)
499 {
500  std::wstring wstr;
501  if (!Utf8toWStr(utf8String, wstr))
502  return false;
503 
504  std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin);
505 
506  return WStrToUtf8(wstr, utf8String);
507 }
wchar_t wcharToUpperOnlyLatin(wchar_t wchar)
Definition: Util.h:273
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:281
bool WStrToUtf8(wchar_t *wstr, size_t size, std::string &utf8str)
Definition: Util.cpp:328

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool Utf8toWStr ( char const utf8str,
size_t  csize,
wchar_t *  wstr,
size_t &  wsize 
)
282 {
283  try
284  {
285  size_t len = utf8::distance(utf8str, utf8str+csize);
286  if (len > wsize)
287  {
288  if (wsize > 0)
289  wstr[0] = L'\0';
290  wsize = 0;
291  return false;
292  }
293 
294  wsize = len;
295  utf8::utf8to16(utf8str, utf8str+csize, wstr);
296  wstr[len] = L'\0';
297  }
298  catch(std::exception)
299  {
300  if (wsize > 0)
301  wstr[0] = L'\0';
302  wsize = 0;
303  return false;
304  }
305 
306  return true;
307 }
std::iterator_traits< octet_iterator >::difference_type distance(octet_iterator first, octet_iterator last)
Definition: checked.h:198
u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result)
Definition: checked.h:234

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool Utf8toWStr ( const std::string &  utf8str,
std::wstring &  wstr 
)
310 {
311  try
312  {
313  if (size_t len = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size()))
314  {
315  wstr.resize(len);
316  utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
317  }
318  }
319  catch(std::exception)
320  {
321  wstr.clear();
322  return false;
323  }
324 
325  return true;
326 }
std::iterator_traits< octet_iterator >::difference_type distance(octet_iterator first, octet_iterator last)
Definition: checked.h:198
u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result)
Definition: checked.h:234

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void utf8truncate ( std::string &  utf8str,
size_t  len 
)
261 {
262  try
263  {
264  size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
265  if (wlen <= len)
266  return;
267 
268  std::wstring wstr;
269  wstr.resize(wlen);
270  utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
271  wstr.resize(len);
272  char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]);
273  utf8str.resize(oend-(&utf8str[0])); // remove unused tail
274  }
275  catch(std::exception)
276  {
277  utf8str.clear();
278  }
279 }
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)
Definition: checked.h:207
std::iterator_traits< octet_iterator >::difference_type distance(octet_iterator first, octet_iterator last)
Definition: checked.h:198
u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result)
Definition: checked.h:234

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vutf8printf ( FILE *  out,
const char *  str,
va_list *  ap 
)
478 {
479 #if PLATFORM == PLATFORM_WINDOWS
480  char temp_buf[32 * 1024];
481  wchar_t wtemp_buf[32 * 1024];
482 
483  size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
484  //vsnprintf returns -1 if the buffer is too small
485  if (temp_len == size_t(-1))
486  temp_len = 32*1024-1;
487 
488  size_t wtemp_len = 32*1024-1;
489  Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
490 
491  CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1));
492  fprintf(out, "%s", temp_buf);
493 #else
494  vfprintf(out, str, *ap);
495 #endif
496 }
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args)
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:281
#define vsnprintf
Definition: Common.h:78
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WStrToUtf8 ( wchar_t *  wstr,
size_t  size,
std::string &  utf8str 
)
329 {
330  try
331  {
332  std::string utf8str2;
333  utf8str2.resize(size*4); // allocate for most long case
334 
335  if (size)
336  {
337  char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]);
338  utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
339  }
340  utf8str = utf8str2;
341  }
342  catch(std::exception)
343  {
344  utf8str.clear();
345  return false;
346  }
347 
348  return true;
349 }
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)
Definition: checked.h:207

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WStrToUtf8 ( std::wstring const wstr,
std::string &  utf8str 
)
352 {
353  try
354  {
355  std::string utf8str2;
356  utf8str2.resize(wstr.size()*4); // allocate for most long case
357 
358  if (wstr.size())
359  {
360  char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str2[0]);
361  utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
362  }
363  utf8str = utf8str2;
364  }
365  catch(std::exception)
366  {
367  utf8str.clear();
368  return false;
369  }
370 
371  return true;
372 }
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)
Definition: checked.h:207

+ Here is the call graph for this function: