示例#1
0
int set_amxstring_utf8(AMX *amx, cell amx_addr, const T *source, size_t sourcelen, size_t maxlen)
{
	size_t len = sourcelen;
	bool needtocheck = false;

	register cell* dest = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
	register cell* start = dest;

	if (len > maxlen)
	{
		len = maxlen;
		needtocheck = true;
	}

	maxlen = len;

	while (maxlen-- && *source)
	{
		*dest++ = *(unsigned char*)source++;
	}

	if (needtocheck && (start[len - 1] & 1 << 7))
	{
		len -= UTIL_CheckValidChar(start + len - 1);
	}

	start[len] = '\0';

	return len;
}
示例#2
0
// native regex_substr(Regex:id, str_id, buffer[], maxLen);
static cell AMX_NATIVE_CALL regex_substr(AMX *amx, cell *params)
{
	int id = params[1]-1;
	if (id >= (int)PEL.length() || id < 0 || PEL[id]->isFree())
	{
		MF_LogError(amx, AMX_ERR_NATIVE, "Invalid regex handle %d", id);
		return 0;
	}

	RegEx *x = PEL[id];
	static char buffer[16384]; // Same as AMXX buffer.

	size_t length;
	size_t maxLength = ke::Min<size_t>(params[4], sizeof(buffer) - 1);

	const char *ret = x->GetSubstring(params[2], buffer, maxLength, &length);

	if (ret == NULL)
	{
		return 0;
	}

	if (length >= maxLength && ret[length - 1] & 1 << 7)
	{
		maxLength -= UTIL_CheckValidChar((char *)ret + length - 1);
	}

	MF_SetAmxString(amx, params[3], ret, maxLength);

	return 1;
}
示例#3
0
void AddString(U **buf_p, size_t &maxlen, const S *string, int width, int prec)
{
	int		size = 0;
	U		*buf;
	static S nlstr[] = {'(','n','u','l','l',')','\0'};

	buf = *buf_p;

	if (string == NULL)
	{
		string = nlstr;
		prec = -1;
	}

	if (prec >= 0)
	{
		for (size = 0; size < prec; size++) 
		{
			if (string[size] == '\0')
				break;
		}
	} else {
		while (string[size++]) ;
		size--;
	}

	if (size > (int)maxlen)
		size = maxlen;

	/* If precision is provided, make sure we don't truncate a multi-byte character */
	if (prec >= size && (string[size - 1] & 1 << 7))
	{
		size -= UTIL_CheckValidChar((cell *)string + size - 1);
	}

	maxlen -= size;
	width -= size;

	while (size--)
		*buf++ = static_cast<U>(*string++);

	while (width-- > 0 && maxlen)
	{
		*buf++ = ' ';
		maxlen--;
	}

	*buf_p = buf;
}
示例#4
0
size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param)
{
	int		arg;
	int		args = params[0] / sizeof(cell);
	D		*buf_p;
	D		ch;
	int		flags;
	int		width;
	int		prec;
	int		n;
	//char	sign;
	const S	*fmt;
	size_t	llen = maxlen;

	buf_p = buffer;
	arg = *param;
	fmt = format;

	while (true)
	{
		// run through the format string until we hit a '%' or '\0'
		for (ch = static_cast<D>(*fmt); 
			llen && ((ch = static_cast<D>(*fmt)) != '\0' && ch != '%');
			fmt++)
		{
			*buf_p++ = static_cast<D>(ch);
			llen--;
		}
		if (ch == '\0' || llen <= 0)
			goto done;

		// skip over the '%'
		fmt++;

		// reset formatting state
		flags = 0;
		width = 0;
		prec = -1;
		//sign = '\0';

rflag:
		ch = static_cast<D>(*fmt++);
reswitch:
		switch(ch)
		{
		case '-':
			flags |= LADJUST;
			goto rflag;
		case '.':
			n = 0;
			while( is_digit( ( ch = static_cast<D>(*fmt++)) ) )
				n = 10 * n + ( ch - '0' );
			prec = n < 0 ? -1 : n;
			goto reswitch;
		case '0':
			flags |= ZEROPAD;
			goto rflag;
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			n = 0;
			do {
				n = 10 * n + ( ch - '0' );
				ch = static_cast<D>(*fmt++);
			} while( is_digit( ch ) );
			width = n;
			goto reswitch;
		case 'c':
			CHECK_ARGS(0);
			*buf_p++ = static_cast<D>(*get_amxaddr(amx, params[arg]));
			llen--;
			arg++;
			break;
		case 'b':
			CHECK_ARGS(0);
			AddBinary(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
			arg++;
			break;
		case 'd':
		case 'i':
			CHECK_ARGS(0);
			AddInt(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
			arg++;
			break;
		case 'u':
			CHECK_ARGS(0);
			AddUInt(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
			arg++;
			break;
		case 'f':
			CHECK_ARGS(0);
			AddFloat(&buf_p, llen, amx_ctof(*get_amxaddr(amx, params[arg])), width, prec, flags);
			arg++;
			break;
		case 'X':
			CHECK_ARGS(0);
			flags |= UPPERDIGITS;
			AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
			arg++;
			break;
		case 'x':
			CHECK_ARGS(0);
			AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
			arg++;
			break;
		case 'a':
			{
				CHECK_ARGS(0);
				// %a is passed a pointer directly to a cell string.
				cell* ptr=reinterpret_cast<cell*>(*get_amxaddr(amx, params[arg]));
				if (!ptr)
				{
					LogError(amx, AMX_ERR_NATIVE, "Invalid vector string handle provided (%d)", *get_amxaddr(amx, params[arg]));
					return 0;
				}

				AddString(&buf_p, llen, ptr, width, prec);
				arg++;
				break;
			}
		case 's':
			CHECK_ARGS(0);
			AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec);
			arg++;
			break;
		case 'L':
		case 'l':
			{
				const char *lang;
				int len;
				if (ch == 'L')
				{
					CHECK_ARGS(1);
					auto currParam = params[arg++];
					lang = playerlang(*get_amxaddr(amx, currParam));
					if (!lang)
						lang = get_amxstring(amx, currParam, 2, len);
				}
				else
				{
					CHECK_ARGS(0);
					lang = playerlang(g_langMngr.GetDefLang());
				}
				const char *key = get_amxstring(amx, params[arg++], 3, len);
				const char *def = translate(amx, lang, key);
				if (!def)
				{
					static char buf[255];
					ke::SafeSprintf(buf, sizeof(buf), "ML_NOTFOUND: %s", key);
					def = buf;
				}
				size_t written = atcprintf(buf_p, llen, def, amx, params, &arg);
				buf_p += written;
				llen -= written;
				break;
			}
		case 'N':
			{
				CHECK_ARGS(0);
				cell *addr = get_amxaddr(amx, params[arg]);
				char buffer[255];
				if (*addr)
				{
					CPlayer *player = NULL;

					if (*addr >= 1 && *addr <= gpGlobals->maxClients)
					{
						player = GET_PLAYER_POINTER_I(*addr);
					}

					if (!player || !player->initialized)
					{
						LogError(amx, AMX_ERR_NATIVE, "Client index %d is invalid", *addr);
						return 0;
					}

					const char *auth = GETPLAYERAUTHID(player->pEdict);
					if (!auth || auth[0] == '\0')
					{
						auth = "STEAM_ID_PENDING";
					}

					int userid = GETPLAYERUSERID(player->pEdict);
					ke::SafeSprintf(buffer, sizeof(buffer), "%s<%d><%s><%s>", player->name.chars(), userid, auth, player->team.chars());
				}
				else
				{
					ke::SafeSprintf(buffer, sizeof(buffer), "Console<0><Console><Console>");
				}

				AddString(&buf_p, llen, buffer, width, prec);
				arg++;
				break;
			}
		case 'n':
			{
				CHECK_ARGS(0);
				cell *addr = get_amxaddr(amx, params[arg]);
				const char *name = "Console";

				if (*addr)
				{
					CPlayer *player = NULL;

					if (*addr >= 1 && *addr <= gpGlobals->maxClients)
					{
						player = GET_PLAYER_POINTER_I(*addr);
					}

					if (!player || !player->initialized)
					{
						LogError(amx, AMX_ERR_NATIVE, "Client index %d is invalid", *addr);
						return 0;
					}

					name = player->name.chars();
				}
			
				AddString(&buf_p, llen, name, width, prec);
				arg++;
				break;
			}
		case '%':
			*buf_p++ = static_cast<D>(ch);
			if (!llen)
				goto done;
			llen--;
			break;
		case '\0':
			*buf_p++ = static_cast<D>('%');
			if (!llen)
				goto done;
			llen--;
			goto done;
			break;
		default:
			*buf_p++ = static_cast<D>(ch);
			if (!llen)
				goto done;
			llen--;
			break;
		}
	}

done:
	*buf_p = static_cast<D>(0);
	*param = arg;

	/* if max buffer length consumed, make sure we don't truncate a multi-byte character */
	if (llen <= 0 && *(buf_p - 1) & 1 << 7)
	{
		llen += UTIL_CheckValidChar(buf_p - 1);
		*(buf_p - llen) = static_cast<D>(0);
	}

	return maxlen-llen;
}
示例#5
0
文件: util.cpp 项目: Javivi/amxmodx
/**
* NOTE: Do not edit this for the love of god unless you have
* read the test cases and understand the code behind each one.
* While I don't guarantee there aren't mistakes, I do guarantee
* that plugins will end up relying on tiny idiosyncrasies of this
* function, just like they did with AMX Mod X.
*
* There are explicitly more cases than the AMX Mod X version because
* we're not doing a blind copy.  Each case is specifically optimized
* for what needs to be done.  Even better, we don't have to error on
* bad buffer sizes.  Instead, this function will smartly cut off the
* string in a way that pushes old data out.
*/
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive)
{
	char *ptr = subject;
	size_t browsed = 0;
	size_t textLen = strlen(subject);

	/* It's not possible to search or replace */
	if (searchLen > textLen)
	{
		return NULL;
	}

	/* Handle the case of one byte replacement.
	* It's only valid in one case.
	*/
	if (maxLen == 1)
	{
		/* If the search matches and the replace length is 0,
		* we can just terminate the string and be done.
		*/
		if ((caseSensitive ? strcmp(subject, search) : strcasecmp(subject, search)) == 0 && replaceLen == 0)
		{
			*subject = '\0';
			return subject;
		}
		else
		{
			return NULL;
		}
	}

	/* Subtract one off the maxlength so we can include the null terminator */
	maxLen--;

	while (*ptr != '\0' && (browsed <= textLen - searchLen))
	{
		/* See if we get a comparison */
		if ((caseSensitive ? strncmp(ptr, search, searchLen) : strncasecmp(ptr, search, searchLen)) == 0)
		{
			if (replaceLen > searchLen)
			{
				/* First, see if we have enough space to do this operation */
				if (maxLen - textLen < replaceLen - searchLen)
				{
					/* First, see if the replacement length goes out of bounds. */
					if (browsed + replaceLen >= maxLen)
					{
						/* EXAMPLE CASE:
						* Subject: AABBBCCC
						* Buffer : 12 bytes
						* Search : BBB
						* Replace: DDDDDDDDDD
						* OUTPUT : AADDDDDDDDD
						* POSITION:           ^
						*/
						/* If it does, we'll just bound the length and do a strcpy. */
						replaceLen = maxLen - browsed;

						/* Note, we add one to the final result for the null terminator */
						strncopy(ptr, replace, replaceLen + 1);

						/* Don't truncate a multi-byte character */
						if (*(ptr + replaceLen - 1) & 1 << 7)
						{
							replaceLen -= UTIL_CheckValidChar(ptr + replaceLen - 1);
							*(ptr + replaceLen) = '\0';
						}
					}
					else
					{
						/* EXAMPLE CASE:
						* Subject: AABBBCCC
						* Buffer : 12 bytes
						* Search : BBB
						* Replace: DDDDDDD
						* OUTPUT : AADDDDDDDCC
						* POSITION:         ^
						*/
						/* We're going to have some bytes left over... */
						size_t origBytesToCopy = (textLen - (browsed + searchLen)) + 1;
						size_t realBytesToCopy = (maxLen - (browsed + replaceLen)) + 1;
						char *moveFrom = ptr + searchLen + (origBytesToCopy - realBytesToCopy);
						char *moveTo = ptr + replaceLen;

						/* First, move our old data out of the way. */
						memmove(moveTo, moveFrom, realBytesToCopy);

						/* Now, do our replacement. */
						memcpy(ptr, replace, replaceLen);
					}
				}
				else
				{
					/* EXAMPLE CASE:
					* Subject: AABBBCCC
					* Buffer : 12 bytes
					* Search : BBB
					* Replace: DDDD
					* OUTPUT : AADDDDCCC
					* POSITION:      ^
					*/
					/* Yes, we have enough space.  Do a normal move operation. */
					char *moveFrom = ptr + searchLen;
					char *moveTo = ptr + replaceLen;

					/* First move our old data out of the way. */
					size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
					memmove(moveTo, moveFrom, bytesToCopy);

					/* Now do our replacement. */
					memcpy(ptr, replace, replaceLen);
				}
			}
			else if (replaceLen < searchLen)
			{
				/* EXAMPLE CASE:
				* Subject: AABBBCCC
				* Buffer : 12 bytes
				* Search : BBB
				* Replace: D
				* OUTPUT : AADCCC
				* POSITION:   ^
				*/
				/* If the replacement does not grow the string length, we do not
				* need to do any fancy checking at all.  Yay!
				*/
				char *moveFrom = ptr + searchLen;		/* Start after the search pointer */
				char *moveTo = ptr + replaceLen;		/* Copy to where the replacement ends */

				/* Copy our replacement in, if any */
				if (replaceLen)
				{
					memcpy(ptr, replace, replaceLen);
				}

				/* Figure out how many bytes to move down, including null terminator */
				size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;

				/* Move the rest of the string down */
				memmove(moveTo, moveFrom, bytesToCopy);
			}
			else
			{
				/* EXAMPLE CASE:
				* Subject: AABBBCCC
				* Buffer : 12 bytes
				* Search : BBB
				* Replace: DDD
				* OUTPUT : AADDDCCC
				* POSITION:     ^
				*/
				/* We don't have to move anything around, just do a straight copy */
				memcpy(ptr, replace, replaceLen);
			}

			return ptr + replaceLen;
		}
		ptr++;
		browsed++;
	}

	return NULL;
}