Example #1
0
/**
*  @brief
*    Gets a AngelScript function declaration
*/
String Script::GetAngelScriptFunctionDeclaration(const String &sFunctionName, const String &sFunctionSignature, bool bCppToAngelScript) const
{
	// Start with the PixelLight function signature (e.g. "void(int,float)")
	String sFunctionDeclaration = sFunctionSignature;

	// Find the index of the "("
	int nIndex = sFunctionDeclaration.IndexOf("(");
	if (nIndex > -1) {

		// [HACK] AngelScript really don't like something like "string MyFunction(string)", it want's "string @MyFunction(const string &)"!
		// I assume that "@" means "AngelScript, take over the control of the given memory". I wasn't able to find the documentation about
		// the AngelScript function declaration syntax, just "scriptstring.cpp" as example.
		if (bCppToAngelScript && sFunctionDeclaration.IndexOf("string") > -1) {
			String sParameters = sFunctionDeclaration.GetSubstring(nIndex);	// Find the parameters part in the string
			sParameters.Replace("string", "const string &");				// Change parameters
			sFunctionDeclaration.Delete(nIndex);							// Remove parameters from original function declaration
			sFunctionDeclaration.Replace("string", "string @");				// Change return
			sFunctionDeclaration += sParameters;							// Construct new function declaration
			nIndex = sFunctionDeclaration.IndexOf("(");						// Update the "(" index
		}

		// Create the AngelScript function declaration (e.g. "void MyFunction(int,float)")
		sFunctionDeclaration.Insert(' ' + sFunctionName, nIndex);
	}

	// Return the AngelScript function declaration (e.g. "void MyFunction(int,float)")
	return sFunctionDeclaration;
}
Example #2
0
ECode CSizeF::ParseSizeF(
    /* [in] */ const String& string,
    /* [out] */ ISizeF** size)
{
    VALIDATE_NOT_NULL(size)
    *size = NULL;

    if (string.IsNull()) {
        return E_ILLEGAL_ARGUMENT_EXCEPTION;
    }
    //checkNotNull(string, "string must not be null");

    Int32 sep_ix = string.IndexOf('*');
    if (sep_ix < 0) {
        sep_ix = string.IndexOf('x');
    }
    if (sep_ix < 0) {
        // throw invalidSize(string);
        return E_NUMBER_FORMAT_EXCEPTION;
    }

    // try {
    Float w, h;
    FAIL_RETURN(StringUtils::Parse(string.Substring(0, sep_ix), &w))
    FAIL_RETURN(StringUtils::Parse(string.Substring(sep_ix + 1), &h))

    AutoPtr<CSizeF> s;
    CSizeF::NewByFriend(w, h, (CSizeF**)&s);
    *size = (ISizeF*)s.Get();
    REFCOUNT_ADD(*size)
    // } catch (NumberFormatException e) {
    //     throw invalidSize(string);
    // }
    return NOERROR;
}
Example #3
0
		Vector<String> String::SplitEmptyEntries(const String& string, const String& delimiter, int count)
		{
			// variables
			int index = 0;
			int lastIndex = -1;
			Vector<String> vector;

			while (index != -1) {
				index = string.IndexOf(delimiter, lastIndex + 1);
				
				if (lastIndex + 1 == index) {
					vector.Add(String());
				} else {
					// TODO: readable calculation
					int startIndex = ((lastIndex == -1) ? (0) : (lastIndex + delimiter._length));
					int length = ((index == -1) ? (string._length - lastIndex - delimiter._length) : (index - lastIndex - delimiter._length));
					vector.Add(String(string._data, startIndex, length));
				}

				lastIndex = index;

				if (vector.Length >= count - 1) {
					// TODO: readable calculation
					int startIndex = ((lastIndex == -1) ? (0) : (lastIndex + delimiter._length));
					int length = ((lastIndex == -1) ? (string._length) : (string._length - lastIndex - delimiter._length));
					vector.Add(String(string._data, startIndex, length));
					return vector;
				}
			}

			return vector;
		}
ECode HttpURLConnection::GetResponseCode(
    /* [out] */ Int32* responseCode)
{
    VALIDATE_NOT_NULL(responseCode)

    // Call getInputStream() first since getHeaderField() doesn't return
    // exceptions
    AutoPtr<IInputStream> is;
    FAIL_RETURN(GetInputStream((IInputStream**)&is));
    String response;
    GetHeaderField(0, &response);
    if (response.IsNull()) {
        *responseCode = -1;
        return NOERROR;
    }
    response = response.Trim();
    Int32 mark = response.IndexOf(" ") + 1;
    if (mark == 0) {
        *responseCode = -1;
        return NOERROR;
    }
    Int32 last = mark + 3;
    if (last > response.GetLength()) {
        last = response.GetLength();
    }
    mResponseCode = StringUtils::ParseInt32(response.Substring(mark, last));
    if ((last + 1) <= response.GetLength()) {
        mResponseMessage = response.Substring(last + 1);
    }
    *responseCode = mResponseCode;
    return NOERROR;
}
Example #5
0
ECode CKXmlSerializer::WriteAttribute(
    /* [in] */ const String& _ns,
    /* [in] */ const String& name,
    /* [in] */ const String& value)
{
    String ns = _ns;
    if (!mPending) {
//        throw new IllegalStateException("illegal position for attribute");
        return E_ILLEGAL_STATE_EXCEPTION;
    }

    //        int cnt = nspCounts[depth];

    if (ns.IsNull()) {
        ns = "";
    }

    //        depth--;
    //        pending = false;

    String prefix("");
    if (!ns.IsEmpty()) {
        FAIL_RETURN(GetPrefix(ns, FALSE, TRUE, &prefix));
    }

    //        pending = true;
    //        depth++;

    /*        if (cnt != nspCounts[depth]) {
                mWriter.write(' ');
                mWriter.write("xmlns");
                if (nspStack[cnt * 2] != null) {
                    mWriter.write(':');
                    mWriter.write(nspStack[cnt * 2]);
                }
                mWriter.write("=\"");
                writeEscaped(nspStack[cnt * 2 + 1], '"');
                mWriter.write('"');
            }
            */

    FAIL_RETURN(IWriter::Probe(mWriter)->Write(' '));
    if (!prefix.IsEmpty()) {
        FAIL_RETURN(IWriter::Probe(mWriter)->Write(prefix));
        FAIL_RETURN(IWriter::Probe(mWriter)->Write(':'));
    }
    FAIL_RETURN(IWriter::Probe(mWriter)->Write(name));
    FAIL_RETURN(IWriter::Probe(mWriter)->Write('='));
    Char32 q = value.IndexOf('"') == -1 ? '"' : '\'';
    FAIL_RETURN(IWriter::Probe(mWriter)->Write(q));
    FAIL_RETURN(WriteEscaped(value, q));
    return IWriter::Probe(mWriter)->Write(q);
}
Example #6
0
Int32 UrlUtils::FindFirstOf(
    /* [in] */ const String& string,
    /* [in] */ const String& chars,
    /* [in] */ Int32 start,
    /* [in] */ Int32 end)
{
    AutoPtr<ArrayOf<Char32> > char32Array = string.GetChars();
    for (Int32 i = start; i < end; i++) {
        if (chars.IndexOf((*char32Array)[i]) != -1) {
            return i;
        }
    }
    return end;
}
Example #7
0
static status_t ExpandFilePathWildCardsAux(const String & curDir, const String & path, Queue<String> & outputPaths, bool isSimpleFormat)
{
   const char * fs = GetFilePathSeparator();
   const int32 sepIdx = path.IndexOf(fs);
   const String firstClause  = (sepIdx >= 0) ? path.Substring(0, sepIdx) : path;
   const String restOfString = (sepIdx >= 0) ? path.Substring(sepIdx+1) : GetEmptyString();

   StringMatcher sm(firstClause, isSimpleFormat);
   Directory dir(curDir());
   if (dir.IsValid())
   {
      if (CanWildcardStringMatchMultipleValues(firstClause))
      {
         while(1)
         {
            const char * fn = dir.GetCurrentFileName();
            if (fn)
            {
               if ((strcmp(fn, ".") != 0)&&(strcmp(fn, "..") != 0)&&((fn[0] != '.')||(firstClause.StartsWith(".")))&&(sm.Match(fn)))
               {
                  const String childPath = String(dir.GetPath())+fn;
                  if (restOfString.HasChars())
                  {
                     if (ExpandFilePathWildCardsAux(childPath, restOfString, outputPaths, isSimpleFormat) != B_NO_ERROR) return B_ERROR;
                  }
                  else if (outputPaths.AddTail(childPath) != B_NO_ERROR) return B_ERROR;
               } 
               dir++;
            }
            else break;
         }
      }
      else
      {
         const String childPath = String(dir.GetPath())+firstClause;
         if (FilePathInfo(childPath()).Exists())
         {
            if (restOfString.HasChars())
            {
               if (ExpandFilePathWildCardsAux(childPath, restOfString, outputPaths, isSimpleFormat) != B_NO_ERROR) return B_ERROR;
            }
            else if (outputPaths.AddTail(childPath) != B_NO_ERROR) return B_ERROR;
         }
      }
   }
   return B_NO_ERROR;
}
Example #8
0
String UrlUtils::GetSchemePrefix(
    /* [in] */const String& spec)
{
    Int32 colon = spec.IndexOf(':');

    if (colon < 1) {
        return String(NULL);
    }

    AutoPtr<ArrayOf<Char32> > char32Array = spec.GetChars();
    for (int i = 0; i < colon; i++) {
        if (!IsValidSchemeChar(i, (Byte)(*char32Array)[i])) {
            return String(NULL);
        }
    }

    String result = spec.Substring(0, colon).ToLowerCase();
    return result;
}
Example #9
0
		Vector<String> String::SplitNoEmptyEntries(const String& string, const String& delimiter, int count)
		{
			// variables
			int index = 0;
			int lastIndex = -1;
			Vector<String> vector;

			while ((index = string.IndexOf(delimiter, index)) != -1) {
				if (lastIndex + 1 != index) {
					vector.Add(String(string._data, lastIndex + delimiter.Length, index - lastIndex - 1));
				}

				lastIndex = index;

				if (vector.Length >= count - 1) {
					vector.Add(String(string._data, lastIndex + delimiter.Length, string._length - index - 1));
					return vector;
				}
			}
		}
Example #10
0
ECode CURI::ParseAuthority(
    /* [in] */ Boolean forceServer)
{
    if (mAuthority.IsNull()) {
        return NOERROR;
    }

    String tempUserInfo;
    String temp = mAuthority;
    Int32 index = temp.IndexOf('@');
    Int32 hostIndex = 0;
    if (index != -1) {
        // remove user info
        tempUserInfo = temp.Substring(0, index);
        FAIL_RETURN(ValidateUserInfo(mAuthority, tempUserInfo, 0));
        temp = temp.Substring(index + 1); // host[:port] is left
        hostIndex = index + 1;
    }

    index = temp.LastIndexOf(':');
    Int32 endIndex = temp.IndexOf(']');

    String tempHost;
    Int32 tempPort = -1;
    if (index != -1 && endIndex < index) {
        // determine port and host
        tempHost = temp.Substring(0, index);

        Char32 firstPortChar = temp.GetChar(index + 1);
        if (firstPortChar >= '0' && firstPortChar <= '9') {
            // allow only digits, no signs
            ECode ec = StringUtils::Parse(temp.Substring(index + 1), &tempPort);
            if (ec == (ECode)E_NUMBER_FORMAT_EXCEPTION) {
                if (forceServer) {
                    ALOGE("%s Invalid port number %d", mAuthority.string(), hostIndex + index + 1);
                    return E_URI_SYNTAX_EXCEPTION;
                }
                return NOERROR;
            }
        } else {
            if (forceServer) {
                ALOGE("%s Invalid port number %d", mAuthority.string(), hostIndex + index + 1);
                return E_URI_SYNTAX_EXCEPTION;
            }
            return NOERROR;
        }
    }
    else {
        tempHost = temp;
    }

    if (tempHost.IsEmpty()) {
        if (forceServer) {
            return E_URI_SYNTAX_EXCEPTION;
        }
        return NOERROR;
    }

    Boolean isValid = FALSE;
    FAIL_RETURN(IsValidHost(forceServer, tempHost, &isValid));
    if (!isValid) {
        return NOERROR;
    }

    // this is a server based uri,
    // fill in the userInfo, host and port fields
    mUserInfo = tempUserInfo;
    mHost = tempHost;
    mPort = tempPort;
    mServerAuthority = TRUE;

    return NOERROR;
}
Example #11
0
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
bool VoidBot::PublicCommands(const char* SessionID, const String& Command)
{
// todo: these should all be busted out into their own functions

	// "Message For" command
	String keyword("message for");
	int32 pos = WholeWordPos(Command, keyword.Cstr());
	if( B_ERROR != pos )
	{
		if( 2048 < Command.Length() )
		{
			SendMessage(SessionID, "There is _no way_ I can remember all that, please phrase the message shorter.");
			return true;
		}

		pos += keyword.Length();
		String name(GetNick(Command, pos));
		if( 0 == name.Length() )
		{
			SendMessage(SessionID, "Please specify a nick!");
			return true;
		}

		if( B_ERROR != name.IndexOf(' ') )
		{
			// name with space, adjust for delimiter chars.
			pos += 2;
		}

		pos += name.Length() + 1;

		if( (int32)Command.Length() < (pos - 1) )
		{
			SendMessage(SessionID, "Please specify a message.");
			return true;
		}

		String message("Message from ");
		message += fData.UserByID(SessionID)->Name();
		message += " Left at";
		message += " [";
		message += Time();
		message += "]";
		message += ": ";
		message += Command.Substring(pos);
		fMessagesForName[name].push_back(message);
		SendPrivateMessage(SessionID, "Will there be anything else?.");
		fReportedNewMessages[name] = false;
		return true;
	}

	// "Seen" command
	keyword = "seen";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( -1 != pos )
	{
		pos += keyword.Length();

		String name(GetNick(Command, pos));
		if( 0 == name.Length() )
		{
			SendMessage(SessionID, "Please specify a nick!");
			return true;
		}

		if( fLastWords.find(name.Cstr()) != fLastWords.end() )
		{
			String info(name);
			info += " was last seen ";
			info += fLastWords[name.Cstr()];
			SendMessage(SessionID, info.Cstr());
		}
		else
		{
			String negatory("No, I haven't seen ");
			negatory += name;
			SendMessage(SessionID, negatory.Cstr());
		}
		return true;
	}

		//*****************<FORTUNE ADDED BY MISZA>************************//
	pos = WholeWordPos(Command, "fortune");
	if(-1 != pos)
	{
		FILE *fp = popen ("fortune", "r");
		if(fp != NULL)
		{
			char ch;
			String cool= "\n";

			while((ch = fgetc(fp))!= EOF)
			{
				cool += ch;
			}

			fclose(fp);
			if(cool != "\n")
			{
				cool = cool.Substring(0,(cool.Length()-1));
				SendPrivateMessage(SessionID,cool.Cstr());
			}
		}
		return true;
	}
	//*****************</FORTUNE ADDED BY MISZA>************************//

	// "GMTime" command
	pos = WholeWordPos(Command, "gmtime");
	if( -1 != pos )
	{
		String info("The time is: ");
		info += Time();
		SendMessage(SessionID, info.Cstr());
		return true;
	}

	// "Time" command
	pos = WholeWordPos(Command, "time");
	if( -1 != pos )
	{
		String info("The time is: ");
		info += MyTime();
		SendMessage(SessionID, info.Cstr());
		return true;
	}

	// "iTime" command
	pos = WholeWordPos(Command, "itime");
	if( -1 != pos )
	{
		String info("The time is: ");
		info += NetTime();
		SendMessage(SessionID, info.Cstr());
		return true;
	}

	// "Atrus" Prevent messages to bebop
	keyword = "message for bebop";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( B_ERROR != pos )
	{
		SendPrivateMessage(SessionID, "You didn't say the magic word...");

			return true;
	}

	// "Atrus" Prevent messages to Atrus
	keyword = "message for Atrus";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( B_ERROR != pos )
	{
		SendPrivateMessage(SessionID, "You didn't say the magic word...");

			return true;
	}

	// "Atrus" Prevent messages to Bubbles
	keyword = "message for Bubbles";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( B_ERROR != pos )
	{
		SendPrivateMessage(SessionID, "You didn't say the magic word...");

			return true;
	}

	// "Atrus" Prevent messages to FAQbot
	keyword = "message for FAQbot";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( B_ERROR != pos )
	{
		SendPrivateMessage(SessionID, "You didn't say the magic word...");

			return true;
	}

	// "Messages" command
	pos = WholeWordPos(Command, "messages");
	if( B_ERROR != pos )
	{
		bool messages = false;
		uint32 quantity = 0;
		const char* name = fData.UserByID(SessionID)->Name();

		if( fMessagesForName.find(name) != fMessagesForName.end() )
		{
			quantity = fMessagesForName[name].size();

			if( quantity != 0 )
			{
				messages = true;
			}
		}

		if( true == messages )
		{
			for( uint32 i = 0; i < quantity; i++ )
			{
				SendPrivateMessage(SessionID, fMessagesForName[name][i].Cstr());
			}

			fMessagesForName[name].clear();
			fReportedNewMessages[name] = true;
		}
		else
		{
			String reply("Sorry ");
			reply += fData.UserByID(SessionID)->Name();
			reply += ", You get nothing and like it!";
			SendPrivateMessage(SessionID, reply.Cstr());
		}

		return true;
	}

	// "Version" command
	pos = WholeWordPos(Command, "version");
	if( B_ERROR != pos )
	{
		// The version string is made up of MAJOR_RELEASE.MINOR_RELEASE.BUG_FIXES
		SendPrivateMessage(SessionID, "I am at version 2.1 (MUSCLE " MUSCLE_VERSION_STRING ")");
		return true;
	}

	pos = WholeWordPos(Command, "catsup");
	if( B_ERROR != pos )
	{
		// Figure out how many lines of chat to return
		pos++;
		pos += strlen("catsup");

		uint32 lines;
		if( (uint32)pos < Command.Length() )
		{
			lines = (uint32)atoi(&(Command.Cstr()[pos]));
			if( 0 == lines )
			{
				lines = kDefaultChatHistory;
			}
		}
		else
		{
			lines = 25;
		}

		if( lines > fChatHistory.size() )
		{
			lines = fChatHistory.size();
		}

		String chatText("\n");
		for( uint32 i = lines; i > 0 ; i-- )
		{
			chatText += fChatHistory[i-1];
			chatText += "\n";
		}

		SendPrivateMessage(SessionID, chatText.Cstr());
		return true;
	}

	// "Email" command
	keyword = "email";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( -1 != pos )
	{
		pos += keyword.Length();

		String name(GetNick(Command, pos));
		if( 0 == name.Length() )
		{
			SendPrivateMessage(SessionID, "Please specify a nick!");
			return true;
		}

		{
			String fullname(botPath);
			fullname += "/email/";
			fullname += name;
			if(!SendTextfile(SessionID, fullname.Cstr(), false))
			{
				SendPrivateMessage(SessionID, "No email address found for that nick!");
			}
			return true;
		}
	}

	// "Gimme" command (v.2)
	keyword = "gimme";
	pos = WholeWordPos(Command, keyword.Cstr());
	if( -1 != pos )
	{
		pos += keyword.Length();

		String name(GetNick(Command, pos));
		if( 0 == name.Length() )
		{
			SendPrivateMessage(SessionID, "Please specify help page!");
			return true;
		}

		{
			String fullname(botPath);
			fullname += "/faq/";
			fullname += name;
			return SendTextfile(SessionID, fullname.Cstr(), false);
		}
	}

	// Do all one word commands (aka send text file with same name to user)
	String name(Command.Substring( Command.IndexOf(" ") + 1));
	if ( 0 < name.Length() )
	{
		String fullname(botPath);
		fullname += "/commands/";
		fullname += name.Cstr();
		return SendTextfile(SessionID, fullname.Cstr(), false);
	}

	return false;
}
// Parses a string that the user typed in to stdin and creates a Message to send to the server.
static MessageRef ParseStdinCommand(const String & stdinCommand)
{
   if (stdinCommand.IsEmpty()) return MessageRef();

   StringTokenizer tok(stdinCommand(), " ");
   const String cmd  = tok();
   if ((cmd == "set") || (cmd == "s"))
   {
      const String theRest = String(tok.GetRemainderOfString());
      if (theRest.HasChars())
      {
         const int eqIdx = theRest.IndexOf('=');
         const String pathArg = (eqIdx >= 0) ? theRest.Substring(0, eqIdx).Trim() : theRest;
         const String dataArg = (eqIdx >= 0) ? theRest.Substring(eqIdx+1).Trim()  : "default";

         if (pathArg.StartsWith("/"))
         {
            LogTime(MUSCLE_LOG_ERROR, "PR_COMMAND_SETDATA paths cannot start with a slash (because you're only allowed to set nodes within your own session-folder!)\n");
         }
         else
         {
            LogTime(MUSCLE_LOG_INFO, "Sending PR_COMMAND_SETDATA to set node at subpath [%s] to contain a Message containing data string [%s]\n", pathArg(), dataArg());
            if (HasRegexTokens(pathArg)) LogTime(MUSCLE_LOG_WARNING, "Note: PR_COMMAND_SETDATA won't do pattern-matching on wildcard chars; rather they will become literal chars in the node-path!\n");

             MessageRef dataPayloadMsg = GetMessageFromPool();
             dataPayloadMsg()->AddString("User String", dataArg);

             MessageRef setDataMsg = GetMessageFromPool(PR_COMMAND_SETDATA);
             setDataMsg()->AddMessage(pathArg, dataPayloadMsg);

             return setDataMsg;
         }
      }
      else LogTime(MUSCLE_LOG_INFO, "Usage Example:  set my_node_dir/my_node_file = some text to put in the node\n");
   }
   else if ((cmd == "get") || (cmd == "g"))
   {
      const String pathArg = tok();
      if (pathArg.HasChars())
      {
         LogTime(MUSCLE_LOG_INFO, "Sending PR_COMMAND_GETDATA to do a one-time download of nodes matching the following path: [%s]\n", pathArg());

         MessageRef getDataMsg = GetMessageFromPool(PR_COMMAND_GETDATA);
         getDataMsg()->AddString(PR_NAME_KEYS, pathArg);
         return getDataMsg;
      }
      else LogTime(MUSCLE_LOG_INFO, "Usage Example:  get /*/*\n");
   }
   else if ((cmd == "delete") || (cmd == "d"))
   {
      const String pathArg = tok();
      if (pathArg.HasChars())
      {
         LogTime(MUSCLE_LOG_INFO, "Sending PR_COMMAND_REMOVEDATA to delete any nodes matching the following path: [%s]\n", pathArg());

         MessageRef deleteNodesMsg = GetMessageFromPool(PR_COMMAND_REMOVEDATA);
         deleteNodesMsg()->AddString(PR_NAME_KEYS, pathArg);
         return deleteNodesMsg;
      }
      else LogTime(MUSCLE_LOG_INFO, "Usage Example:  delete *\n");
   }
   else if ((cmd == "subscribe") || (cmd == "S"))
   {
      const String pathArg = tok();
      if (pathArg.HasChars())
      {
         LogTime(MUSCLE_LOG_INFO, "Sending PR_COMMAND_SETPARAMETERS to set up a \"live\" subscription to any nodes matching the following path: [%s]\n", pathArg());

         MessageRef subscribeToNodesMsg = GetMessageFromPool(PR_COMMAND_SETPARAMETERS);
         subscribeToNodesMsg()->AddBool(String("SUBSCRIBE:%1").Arg(pathArg), true);
         return subscribeToNodesMsg;
      }
      else LogTime(MUSCLE_LOG_INFO, "Usage Example:  subscribe /*/*\n");
   }
   else if ((cmd == "unsubscribe") || (cmd == "u"))
   {
      const String pathArg = tok();
      if (pathArg.HasChars())
      {
         LogTime(MUSCLE_LOG_INFO, "Sending PR_COMMAND_REMOVEPARAMETERS to get rid of any \"live\" subscriptions that match the following string: [SUBSCRIBE:%s]\n", pathArg());

         MessageRef unsubscribeFromNodesMsg = GetMessageFromPool(PR_COMMAND_REMOVEPARAMETERS);
         unsubscribeFromNodesMsg()->AddString(PR_NAME_KEYS, String("SUBSCRIBE:%1").Arg(pathArg));
         return unsubscribeFromNodesMsg;
      }
      else LogTime(MUSCLE_LOG_INFO, "Usage Example:  unsubscribe /*/*\n");
   }
   else if ((cmd == "msg") || (cmd == "m"))
   {
      const String pathArg  = tok();
      if (pathArg.HasChars())
      {
         const String userText = tok.GetRemainderOfString();

         MessageRef chatMsg = GetMessageFromPool(1234);  // any non-PR_COMMAND_* message code will work here
         chatMsg()->AddString(PR_NAME_KEYS, pathArg);
         chatMsg()->AddString("chat_text", userText);
         return chatMsg;
      }
      else LogTime(MUSCLE_LOG_INFO, "Usage Example:  msg /*/* Hey guys!\n");
   }
   else if ((cmd == "help") || (cmd == "h"))
   {
      PrintHelp();
   }
   else LogTime(MUSCLE_LOG_ERROR, "Couldn't parse stdin command [%s].  Enter help to review the command-help-text.\n", stdinCommand());

   return MessageRef();  // nothing to send for now
}