Browse Source

added getToken() and gotoToken().

release/0.19
JustinAJ 11 years ago
parent
commit
f12b36f350
  1. 26
      Jupiter/Readable_String.h
  2. 90
      Jupiter/Readable_String_Imp.h
  3. 42
      Jupiter/Reference_String.h
  4. 40
      Jupiter/Reference_String_Imp.h
  5. 84
      Jupiter/String.h
  6. 80
      Jupiter/String_Imp.h
  7. BIN
      Release/Jupiter.lib

26
Jupiter/Readable_String.h

@ -246,6 +246,19 @@ namespace Jupiter
template<template<typename> class R> static R<T> getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace); template<template<typename> class R> static R<T> getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
template<template<typename> class R> static R<T> getWord(const T *in, size_t pos, const T *whitespace); template<template<typename> class R> static R<T> getWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Copies a the elements between two tokens from an input string and returns it in an output type.
*
* @param R Type to return. Must be a subclass of String_Type.
*
* @param in String to get a partial copy of.
* @param pos Index of the token to copy.
* @param token Token to scan for.
* @return Copy of the token at the specified index on success, an empty string otherwise.
*/
template<template<typename> class R> static R<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
template<template<typename> class R> static R<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** /**
* @brief Copies a part of an input string starting at a specified "word" and returns it in an output type. * @brief Copies a part of an input string starting at a specified "word" and returns it in an output type.
* *
@ -259,6 +272,19 @@ namespace Jupiter
template<template<typename> class R> static R<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace); template<template<typename> class R> static R<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
template<template<typename> class R> static R<T> gotoWord(const T *in, size_t pos, const T *whitespace); template<template<typename> class R> static R<T> gotoWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Copies a part of an input string starting at a specified token and returns it in an output type.
*
* @param R Type to return. Must be a subclass of String_Type.
*
* @param in String to get a partial copy of.
* @param pos Index of the word to start copying from.
* @param token Token to scan for.
* @return Copy of the string starting at the specified word on success, an empty string otherwise.
*/
template<template<typename> class R> static R<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
template<template<typename> class R> static R<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** Access operator */ /** Access operator */
inline const T &operator[](size_t index) const { return this->get(index); }; inline const T &operator[](size_t index) const { return this->get(index); };

90
Jupiter/Readable_String_Imp.h

@ -983,6 +983,59 @@ template<typename T> template<template<typename> class R> R<T> Jupiter::Readable
return R<T>::substring(in, x, y - x); return R<T>::substring(in, x, y - x);
} }
// getToken
template<typename T> template<template<typename> class R> R<T> Jupiter::Readable_String<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
size_t x, y;
for (x = 0; x != in.size() && pos != 0; x++)
if (in.get(x) == token)
pos--;
for (y = x; y != in.size() && in.get(y) != token; y++);
return R<T>::substring(in, x, y - x);
}
template<typename T> template<template<typename> class R> R<T> Jupiter::Readable_String<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
if (token.size() == 0)
return R<T>(in);
if (token.size() == 1)
return Jupiter::Readable_String<T>::getToken<R>(in, pos, token.get(0));
if (pos == 0)
return R<T>::substring(in, 0, in.find(token));
size_t i, j;
for (i = 0; i != in.size(); i++)
{
Jupiter_Readable_String_getToken_skip_increment:
j = 0;
while (in.get(i + j) == token.get(j))
{
if (++j == token.size())
{
i += j;
if (--pos == 0)
{
size_t k;
for (j = i; j != in.size(); j++)
{
k = 0;
while (in.get(j + k) == token.get(k))
if (++k == token.size())
return R<T>::substring(in, i, j - i);
}
return R<T>::substring(in, i);
}
else
goto Jupiter_Readable_String_getToken_skip_increment;
break;
}
}
}
return R<T>();
}
// gotoWord // gotoWord
template<typename T> template<template<typename> class R> R<T> Jupiter::Readable_String<T>::gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace) template<typename T> template<template<typename> class R> R<T> Jupiter::Readable_String<T>::gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace)
@ -1033,4 +1086,41 @@ template<typename T> template<template<typename> class R> R<T> Jupiter::Readable
return R<T>::substring(in, x); return R<T>::substring(in, x);
} }
// gotoToken
template<typename T> template<template<typename> class R> R<T> Jupiter::Readable_String<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
size_t i;
for (i = 0; i != in.size() && pos != 0; i++)
if (in.get(i) == token)
pos--;
return R<T>::substring(in, i);
}
template<typename T> template<template<typename> class R> R<T> Jupiter::Readable_String<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
if (pos == 0 || token.size() == 0)
return R<T>(in);
if (token.size() == 1)
return Jupiter::Readable_String<T>::gotoToken<R>(in, pos, token.get(0));
size_t i, j;
for (i = 0; i != in.size(); i++)
{
j = 0;
while (in.get(i + j) == token.get(j))
{
if (++j == token.size())
{
if (pos-- == 0)
return R<T>::substring(in, i);
break;
}
}
}
return R<T>();
}
#endif // _READABLE_STRING_IMP_H_HEADER #endif // _READABLE_STRING_IMP_H_HEADER

42
Jupiter/Reference_String.h

@ -163,6 +163,27 @@ namespace Jupiter
*/ */
static Reference_String<T> getWord(const T *in, size_t pos, const T *whitespace); static Reference_String<T> getWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param pos Position of the token in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
Reference_String<T> getToken(size_t pos, const T &token);
Reference_String<T> getToken(size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Creates a partial copy of an input string, based on a token.
*
* @param in String to get a partial copy of.
* @param pos Position of the token in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
static Reference_String<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static Reference_String<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** /**
* @brief Creates a partial copy of the string, based on a set of tokens. * @brief Creates a partial copy of the string, based on a set of tokens.
* *
@ -192,6 +213,27 @@ namespace Jupiter
*/ */
static Reference_String<T> gotoWord(const T *in, size_t pos, const T *whitespace); static Reference_String<T> gotoWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param pos Position in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
Reference_String<T> gotoToken(size_t pos, const T &token);
Reference_String<T> gotoToken(size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
static Reference_String<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static Reference_String<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** /**
* @brief Default constructor for the Reference_String class. * @brief Default constructor for the Reference_String class.
*/ */

40
Jupiter/Reference_String_Imp.h

@ -176,6 +176,26 @@ template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::
return Jupiter::Readable_String<T>::getWord<Jupiter::Reference_String>(in, pos, whitespace); return Jupiter::Readable_String<T>::getWord<Jupiter::Reference_String>(in, pos, whitespace);
} }
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::getToken(size_t pos, const T &token)
{
return Jupiter::Reference_String<T>::getToken(*this, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::getToken(size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Reference_String<T>::getToken(*this, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
return Jupiter::Readable_String<T>::getToken<Jupiter::Reference_String>(in, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Readable_String<T>::getToken<Jupiter::Reference_String>(in, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::gotoWord(size_t pos, const T *whitespace) const template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::gotoWord(size_t pos, const T *whitespace) const
{ {
return Jupiter::Reference_String<T>::gotoWord(*this, pos, whitespace); return Jupiter::Reference_String<T>::gotoWord(*this, pos, whitespace);
@ -191,6 +211,26 @@ template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::
return Jupiter::Readable_String<T>::gotoWord<Jupiter::Reference_String>(in, pos, whitespace); return Jupiter::Readable_String<T>::gotoWord<Jupiter::Reference_String>(in, pos, whitespace);
} }
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::gotoToken(size_t pos, const T &token)
{
return Jupiter::Reference_String<T>::gotoToken(*this, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::gotoToken(size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Reference_String<T>::gotoToken(*this, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
return Jupiter::Readable_String<T>::gotoToken<Jupiter::Reference_String>(in, pos, token);
}
template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Readable_String<T>::gotoToken<Jupiter::Reference_String>(in, pos, token);
}
template<typename T> const Jupiter::Reference_String<T> Jupiter::Reference_String<T>::empty = Jupiter::Reference_String<T>(); template<typename T> const Jupiter::Reference_String<T> Jupiter::Reference_String<T>::empty = Jupiter::Reference_String<T>();
#endif // _REFERENCE_STRING_IMP #endif // _REFERENCE_STRING_IMP

84
Jupiter/String.h

@ -136,6 +136,27 @@ namespace Jupiter
*/ */
static String_Strict<T> getWord(const T *in, size_t pos, const T *whitespace); static String_Strict<T> getWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param pos Position of the token in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
String_Strict<T> getToken(size_t pos, const T &token);
String_Strict<T> getToken(size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Creates a partial copy of an input string, based on a token.
*
* @param in String to get a partial copy of.
* @param pos Position of the token in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
static String_Strict<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static String_Strict<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** /**
* @brief Creates a partial copy of the string, based on a set of tokens. * @brief Creates a partial copy of the string, based on a set of tokens.
* *
@ -155,6 +176,27 @@ namespace Jupiter
*/ */
static String_Strict<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace); static String_Strict<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param pos Position in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
String_Strict<T> gotoToken(size_t pos, const T &token);
String_Strict<T> gotoToken(size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
static String_Strict<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static String_Strict<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** Assignment Operators */ /** Assignment Operators */
inline String_Strict<T> &operator=(const String_Strict<T> &right) { this->set(right); return *this; }; inline String_Strict<T> &operator=(const String_Strict<T> &right) { this->set(right); return *this; };
inline String_Strict<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; }; inline String_Strict<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; };
@ -300,6 +342,27 @@ namespace Jupiter
*/ */
static String_Loose<T> getWord(const T *in, size_t pos, const T *whitespace); static String_Loose<T> getWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param pos Position of the token in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
String_Loose<T> getToken(size_t pos, const T &token);
String_Loose<T> getToken(size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Creates a partial copy of an input string, based on a token.
*
* @param in String to get a partial copy of.
* @param pos Position of the token in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
static String_Loose<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static String_Loose<T> getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** /**
* @brief Creates a partial copy of the string, based on a set of tokens. * @brief Creates a partial copy of the string, based on a set of tokens.
* *
@ -319,6 +382,27 @@ namespace Jupiter
*/ */
static String_Loose<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace); static String_Loose<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param pos Position in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
String_Loose<T> gotoToken(size_t pos, const T &token);
String_Loose<T> gotoToken(size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Creates a partial copy of the string, based on a token.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @param token Token to scan for.
* @return String containing a partial copy of the original string.
*/
static String_Loose<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static String_Loose<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/** Default constructor */ /** Default constructor */
String_Loose(); String_Loose();

80
Jupiter/String_Imp.h

@ -216,6 +216,26 @@ template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::getWor
return Jupiter::Readable_String<T>::getWord<Jupiter::String_Strict>(in, pos, whitespace); return Jupiter::Readable_String<T>::getWord<Jupiter::String_Strict>(in, pos, whitespace);
} }
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::getToken(size_t pos, const T &token)
{
return Jupiter::String_Strict<T>::getToken(*this, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::getToken(size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::String_Strict<T>::getToken(*this, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
return Jupiter::Readable_String<T>::getToken<Jupiter::String_Strict>(in, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Readable_String<T>::getToken<Jupiter::String_Strict>(in, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoWord(size_t pos, const T *whitespace) const template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoWord(size_t pos, const T *whitespace) const
{ {
return Jupiter::String_Strict<T>::gotoWord(*this, pos, whitespace); return Jupiter::String_Strict<T>::gotoWord(*this, pos, whitespace);
@ -226,6 +246,26 @@ template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoWo
return Jupiter::Readable_String<T>::gotoWord<Jupiter::String_Strict>(in, pos, whitespace); return Jupiter::Readable_String<T>::gotoWord<Jupiter::String_Strict>(in, pos, whitespace);
} }
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoToken(size_t pos, const T &token)
{
return Jupiter::String_Strict<T>::gotoToken(*this, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoToken(size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::String_Strict<T>::gotoToken(*this, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
return Jupiter::Readable_String<T>::gotoToken<Jupiter::String_Strict>(in, pos, token);
}
template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Readable_String<T>::gotoToken<Jupiter::String_Strict>(in, pos, token);
}
template<typename T> const Jupiter::String_Strict<T> Jupiter::String_Strict<T>::empty = Jupiter::String_Strict<T>(); template<typename T> const Jupiter::String_Strict<T> Jupiter::String_Strict<T>::empty = Jupiter::String_Strict<T>();
/** /**
@ -443,6 +483,26 @@ template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::getWord(
return Jupiter::Readable_String<T>::getWord<Jupiter::String_Loose>(in, pos, whitespace); return Jupiter::Readable_String<T>::getWord<Jupiter::String_Loose>(in, pos, whitespace);
} }
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::getToken(size_t pos, const T &token)
{
return Jupiter::String_Loose<T>::getToken(*this, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::getToken(size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::String_Loose<T>::getToken(*this, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
return Jupiter::Readable_String<T>::getToken<Jupiter::String_Loose>(in, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::getToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Readable_String<T>::getToken<Jupiter::String_Loose>(in, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoWord(size_t pos, const T *whitespace) const template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoWord(size_t pos, const T *whitespace) const
{ {
return Jupiter::String_Loose<T>::gotoWord(*this, pos, whitespace); return Jupiter::String_Loose<T>::gotoWord(*this, pos, whitespace);
@ -453,6 +513,26 @@ template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoWord
return Jupiter::Readable_String<T>::gotoWord<Jupiter::String_Loose>(in, pos, whitespace); return Jupiter::Readable_String<T>::gotoWord<Jupiter::String_Loose>(in, pos, whitespace);
} }
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoToken(size_t pos, const T &token)
{
return Jupiter::String_Loose<T>::gotoToken(*this, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoToken(size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::String_Loose<T>::gotoToken(*this, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token)
{
return Jupiter::Readable_String<T>::gotoToken<Jupiter::String_Loose>(in, pos, token);
}
template<typename T> Jupiter::String_Loose<T> Jupiter::String_Loose<T>::gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token)
{
return Jupiter::Readable_String<T>::gotoToken<Jupiter::String_Loose>(in, pos, token);
}
template<typename T> const Jupiter::String_Loose<T> Jupiter::String_Loose<T>::empty = Jupiter::String_Loose<T>(); template<typename T> const Jupiter::String_Loose<T> Jupiter::String_Loose<T>::empty = Jupiter::String_Loose<T>();
#endif // _STRING_IMP_H_HEADER #endif // _STRING_IMP_H_HEADER

BIN
Release/Jupiter.lib

Binary file not shown.
Loading…
Cancel
Save