Leviathan  0.8.0.0
Leviathan game engine
StringOperations.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "StringOperations.h"
3 using namespace Leviathan;
4 // ------------------------------------ //
5 
6 template<>
8  std::wstring& str, const char* characters, size_t count)
9 {
10  // Skip copying null terminator
11  const size_t copysize = count - 1;
12  str.resize(copysize);
13 
14  for(size_t i = 0; i < copysize; ++i)
15  str[i] = (wchar_t)characters[i];
16 }
17 
18 DLLEXPORT std::string StringOperations::URLProtocol(const std::string& url)
19 {
20  const auto colonpos = url.find_first_of(':');
21 
22  if(colonpos == std::string::npos)
23  return "";
24 
25  return url.substr(0, colonpos);
26 }
27 
28 DLLEXPORT std::string StringOperations::BaseHostName(const std::string& url)
29 {
30  if(url.empty())
31  return "";
32 
33  // Start scanning until a '/' is found that is not preceeded by ':' or '/'
34  size_t length = 0;
35 
36  for(size_t i = 0; i < url.size(); ++i) {
37 
38  length = i + 1;
39 
40  if(url[i] == '/') {
41 
42  if(i < 1)
43  continue;
44 
45  if(url[i - 1] == ':' || url[i - 1] == '/')
46  continue;
47 
48  // found it //
49  break;
50  }
51  }
52 
53  // Make sure it has an ending '/'
54  if(length == url.size() && url.back() != '/')
55  return url + "/";
56 
57  return url.substr(0, length);
58 }
59 
61  const std::string& url, bool stripoptions /*= true*/)
62 {
63  if(url.empty())
64  return "";
65 
66  // Start scanning until a '/' is found that is not preceeded by ':' or '/'
67  size_t startCopy = 0;
68 
69  for(size_t i = 0; i < url.size(); ++i) {
70 
71  if(url[i] == '/') {
72 
73  if(i < 1)
74  continue;
75 
76  if(url[i - 1] == ':' || url[i - 1] == '/')
77  continue;
78 
79  // found it //
80  startCopy = i + 1;
81  break;
82  }
83  }
84 
85  // Make sure the string doesn't end there
86  if(startCopy >= url.size())
87  return "";
88 
89  size_t endCopy = url.size();
90 
91  // Scan backwards for cutting options
92  if(stripoptions) {
93  for(size_t cut = endCopy; cut > startCopy; --cut) {
94  if(url[cut] == '?') {
95  // Found options
96  endCopy = cut;
97  break;
98  }
99  }
100  }
101 
102  return url.substr(startCopy, endCopy - startCopy);
103 }
104 
106  const std::string& first, const std::string& second)
107 {
108  // To fix messed up urls we always do this cleanup
109  const auto cleanedUpSecond = RemovePartsBeforeAbsoluteURLParts(second);
110 
111  if(first.empty())
112  return cleanedUpSecond;
113 
114  if(cleanedUpSecond.empty())
115  return first;
116 
117  // If second is an absolute URL just return it //
118  if(cleanedUpSecond.find("://") != std::string::npos)
119  return cleanedUpSecond;
120 
121  // If the other starts with double '//' then we just need to grab the protocol from the
122  // first and add the second
123  if(cleanedUpSecond.find("//") == 0)
124  return URLProtocol(first) + ":" + second;
125 
126  // Simplest case: first ends with '/' and second doesn't begin with '/'
127  if(first.back() == '/' && cleanedUpSecond.front() != '/')
128  return first + cleanedUpSecond;
129 
130  // Second begins with '/': trim the first to the base url and then append the second
131  if(cleanedUpSecond.front() == '/')
132  return BaseHostName(first) + cleanedUpSecond.substr(1);
133 
134  // An error catching function
135  // If first is the basehostname then just combine them
136  if(first.back() != '/' && BaseHostName(first).length() == first.length() + 1)
137  return first + "/" + cleanedUpSecond;
138 
139  // Most complex case: trim from the end of first until the last '/' and then append second
140  const auto lastpos = first.find_last_of('/');
141  return first.substr(0, lastpos + 1) + cleanedUpSecond;
142 }
143 
145  const std::string& url)
146 {
147  // Detect two '//'s in a path
148  const auto colonPos = url.find_first_of(':');
149 
150  if(colonPos != std::string::npos) {
151 
152  // First double slash
153  auto firstDouble = url.find("//", colonPos + 3);
154  // Second
155  const auto secondDouble = url.find("//", firstDouble + 2);
156 
157  if(firstDouble != std::string::npos && secondDouble != std::string::npos) {
158 
159  // If the part between the double slashes looks like a
160  // domain then we cut the part between the protocol and
161  // the first double slash
162  firstDouble += 2;
163 
164  if(IsURLDomain(url.substr(firstDouble, secondDouble - firstDouble))) {
165 
166  return URLProtocol(url) + "://" +
167  url.substr(firstDouble, secondDouble - firstDouble) + "/" +
168  url.substr(secondDouble + 2);
169  }
170  }
171  }
172 
173  return url;
174 }
175 
176 DLLEXPORT bool StringOperations::IsURLDomain(const std::string& str)
177 {
178  // Must have a dot
179  bool dotSeen = false;
180 
181  for(char c : str) {
182  if(c == '.') {
183  dotSeen = true;
184  continue;
185  }
186 
187  if(c >= '0' && c <= '9')
188  continue;
189 
190  if(c >= 'A' && c <= 'Z')
191  continue;
192 
193  if(c >= 'a' && c <= 'z')
194  continue;
195 
196  return false;
197  }
198 
199  return dotSeen;
200 }
static DLLEXPORT std::string CombineURL(const std::string &first, const std::string &second)
static DLLEXPORT std::string BaseHostName(const std::string &url)
static DLLEXPORT std::string URLProtocol(const std::string &url)
static DLLEXPORT std::string URLPath(const std::string &url, bool stripoptions=true)
static DLLEXPORT std::string RemovePartsBeforeAbsoluteURLParts(const std::string &url)
#define DLLEXPORT
Definition: Include.h:84
static void MakeString(StringTypeN &str, const char *characters, size_t count)
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
static DLLEXPORT bool IsURLDomain(const std::string &str)
Returns true if string looks like a top level domain.