core/UserMessagePBHelpers.h
author David Anderson <dvander@alliedmods.net>
Thu Aug 08 20:21:37 2013 -0700 (2013-08-08)
changeset 3978 5bdc0f106c05
parent 3896 cb7537c1da4d
child 4293 f61ae385f12e
permissions -rw-r--r--
Fix Windows build (require stdint.h i.e. MSVC 2010+).
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2013 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #ifndef _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
    33 #define _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
    34 
    35 #include <sh_list.h>
    36 #include <google/protobuf/descriptor.h>
    37 
    38 #define GETCHECK_FIELD() \
    39 	const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
    40 	if (!field)       \
    41 	{                 \
    42 		return false; \
    43 	}
    44 
    45 #define CHECK_FIELD_TYPE(type) \
    46 	if (field->cpp_type() != protobuf::FieldDescriptor::CPPTYPE_##type) \
    47 	{                 \
    48 		return false; \
    49 	}
    50 
    51 #define CHECK_FIELD_TYPE2(type1, type2) \
    52 	protobuf::FieldDescriptor::CppType fieldType = field->cpp_type(); \
    53 	if (fieldType != protobuf::FieldDescriptor::CPPTYPE_##type1       \
    54 		&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type2) \
    55 	{                 \
    56 		return false; \
    57 	}
    58 
    59 #define CHECK_FIELD_TYPE3(type1, type2, type3) \
    60 	protobuf::FieldDescriptor::CppType fieldType = field->cpp_type(); \
    61 	if (fieldType != protobuf::FieldDescriptor::CPPTYPE_##type1       \
    62 		&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type2 \
    63 		&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type3) \
    64 	{                 \
    65 		return false; \
    66 	}
    67 
    68 #define CHECK_FIELD_REPEATED() \
    69 	if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \
    70 	{                 \
    71 		return false; \
    72 	}
    73 
    74 #define CHECK_FIELD_NOT_REPEATED() \
    75 	if (field->label() == protobuf::FieldDescriptor::LABEL_REPEATED) \
    76 	{                 \
    77 		return false; \
    78 	}
    79 
    80 #define CHECK_REPEATED_ELEMENT(idx) \
    81 	int elemCount = msg->GetReflection()->FieldSize(*msg, field); \
    82 	if (elemCount == 0 || idx >= elemCount || idx < 0)        \
    83 	{                                                         \
    84 		return false;                                         \
    85 	}
    86 
    87 typedef List<Handle_t> PBHandleList;
    88 
    89 class SMProtobufMessage
    90 {
    91 public:
    92 	SMProtobufMessage( protobuf::Message *message )
    93 	{
    94 		msg = message;
    95 	}
    96 
    97 	~SMProtobufMessage()
    98 	{
    99 		PBHandleList::iterator iter = childHandles.begin();
   100 		while (iter != childHandles.end())
   101 		{
   102 			Handle_t &hndl = (*iter);
   103 			HandleSecurity sec;
   104 			sec.pIdentity = g_pCoreIdent;
   105 			handlesys->FreeHandle(hndl, &sec);
   106 			iter = childHandles.erase(iter);
   107 		}
   108 	}
   109 
   110 	inline void AddChildHandle(Handle_t hndl)
   111 	{
   112 		childHandles.push_back(hndl);
   113 	}
   114 
   115 	inline protobuf::Message *GetProtobufMessage()
   116 	{
   117 		return msg;
   118 	}
   119 
   120 	inline bool GetInt32(const char *pszFieldName, int32 *out)
   121 	{
   122 		GETCHECK_FIELD();
   123 		CHECK_FIELD_TYPE(INT32);
   124 		CHECK_FIELD_NOT_REPEATED();
   125 
   126 		*out = msg->GetReflection()->GetInt32(*msg, field);
   127 		return true;	
   128 	}
   129 
   130 	inline bool SetInt32(const char *pszFieldName, int32 value)
   131 	{
   132 		GETCHECK_FIELD();
   133 		CHECK_FIELD_TYPE(INT32);
   134 		CHECK_FIELD_NOT_REPEATED();
   135 
   136 		msg->GetReflection()->SetInt32(msg, field, value);
   137 		return true;
   138 	}
   139 
   140 	inline bool GetRepeatedInt32(const char *pszFieldName, int index, int32 *out)
   141 	{
   142 		GETCHECK_FIELD();
   143 		CHECK_FIELD_TYPE(INT32);
   144 		CHECK_FIELD_REPEATED();
   145 		CHECK_REPEATED_ELEMENT(index);
   146 		
   147 		*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
   148 		return true;
   149 	}
   150 
   151 	inline bool SetRepeatedInt32(const char *pszFieldName, int index, int32 value)
   152 	{
   153 		GETCHECK_FIELD();
   154 		CHECK_FIELD_TYPE(INT32);
   155 		CHECK_FIELD_REPEATED();
   156 		CHECK_REPEATED_ELEMENT(index);
   157 		
   158 		msg->GetReflection()->SetRepeatedInt32(msg, field, index, value);
   159 		return true;
   160 	}
   161 
   162 	inline bool AddInt32(const char *pszFieldName, int32 value)
   163 	{
   164 		GETCHECK_FIELD();
   165 		CHECK_FIELD_TYPE(INT32);
   166 		CHECK_FIELD_REPEATED();
   167 
   168 		msg->GetReflection()->AddInt32(msg, field, value);
   169 		return true;
   170 	}
   171 
   172 	inline bool GetInt64(const char *pszFieldName, int64 *out)
   173 	{
   174 		GETCHECK_FIELD();
   175 		CHECK_FIELD_TYPE(INT64);
   176 		CHECK_FIELD_NOT_REPEATED();
   177 
   178 		*out = msg->GetReflection()->GetInt64(*msg, field);
   179 		return true;	
   180 	}
   181 
   182 	inline bool SetInt64(const char *pszFieldName, int64 value)
   183 	{
   184 		GETCHECK_FIELD();
   185 		CHECK_FIELD_TYPE(INT64);
   186 		CHECK_FIELD_NOT_REPEATED();
   187 
   188 		msg->GetReflection()->SetInt64(msg, field, value);
   189 		return true;
   190 	}
   191 
   192 	inline bool GetRepeatedInt64(const char *pszFieldName, int index, int64 *out)
   193 	{
   194 		GETCHECK_FIELD();
   195 		CHECK_FIELD_TYPE(INT64);
   196 		CHECK_FIELD_REPEATED();
   197 		CHECK_REPEATED_ELEMENT(index);
   198 		
   199 		*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
   200 		return true;
   201 	}
   202 
   203 	inline bool SetRepeatedInt64(const char *pszFieldName, int index, int64 value)
   204 	{
   205 		GETCHECK_FIELD();
   206 		CHECK_FIELD_TYPE(INT64);
   207 		CHECK_FIELD_REPEATED();
   208 		CHECK_REPEATED_ELEMENT(index);
   209 		
   210 		msg->GetReflection()->SetRepeatedInt64(msg, field, index, value);
   211 		return true;
   212 	}
   213 
   214 	inline bool AddInt64(const char *pszFieldName, int64 value)
   215 	{
   216 		GETCHECK_FIELD();
   217 		CHECK_FIELD_TYPE(INT64);
   218 		CHECK_FIELD_REPEATED();
   219 
   220 		msg->GetReflection()->AddInt64(msg, field, value);
   221 		return true;
   222 	}
   223 
   224 	inline bool GetUInt32(const char *pszFieldName, uint32 *out)
   225 	{
   226 		GETCHECK_FIELD();
   227 		CHECK_FIELD_TYPE(UINT32);
   228 		CHECK_FIELD_NOT_REPEATED();
   229 
   230 		*out = msg->GetReflection()->GetUInt32(*msg, field);
   231 		return true;	
   232 	}
   233 
   234 	inline bool SetUInt32(const char *pszFieldName, uint32 value)
   235 	{
   236 		GETCHECK_FIELD();
   237 		CHECK_FIELD_TYPE(UINT32);
   238 		CHECK_FIELD_NOT_REPEATED();
   239 
   240 		msg->GetReflection()->SetUInt32(msg, field, value);
   241 		return true;
   242 	}
   243 
   244 	inline bool GetRepeatedUInt32(const char *pszFieldName, int index, uint32 *out)
   245 	{
   246 		GETCHECK_FIELD();
   247 		CHECK_FIELD_TYPE(UINT32);
   248 		CHECK_FIELD_REPEATED();
   249 		CHECK_REPEATED_ELEMENT(index);
   250 		
   251 		*out = msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
   252 		return true;
   253 	}
   254 
   255 	inline bool SetRepeatedUInt32(const char *pszFieldName, int index, uint32 value)
   256 	{
   257 		GETCHECK_FIELD();
   258 		CHECK_FIELD_TYPE(UINT32);
   259 		CHECK_FIELD_REPEATED();
   260 		CHECK_REPEATED_ELEMENT(index);
   261 		
   262 		msg->GetReflection()->SetRepeatedUInt32(msg, field, index, value);
   263 		return true;
   264 	}
   265 
   266 	inline bool AddUInt32(const char *pszFieldName, uint32 value)
   267 	{
   268 		GETCHECK_FIELD();
   269 		CHECK_FIELD_TYPE(UINT32);
   270 		CHECK_FIELD_REPEATED();
   271 
   272 		msg->GetReflection()->AddUInt32(msg, field, value);
   273 		return true;
   274 	}
   275 
   276 	inline bool GetUInt64(const char *pszFieldName, uint64 *out)
   277 	{
   278 		GETCHECK_FIELD();
   279 		CHECK_FIELD_TYPE(UINT64);
   280 		CHECK_FIELD_NOT_REPEATED();
   281 
   282 		*out = msg->GetReflection()->GetUInt64(*msg, field);
   283 		return true;	
   284 	}
   285 
   286 	inline bool SetUInt64(const char *pszFieldName, uint64 value)
   287 	{
   288 		GETCHECK_FIELD();
   289 		CHECK_FIELD_TYPE(UINT64);
   290 		CHECK_FIELD_NOT_REPEATED();
   291 
   292 		msg->GetReflection()->SetUInt64(msg, field, value);
   293 		return true;
   294 	}
   295 
   296 	inline bool GetRepeatedUInt64(const char *pszFieldName, int index, uint64 *out)
   297 	{
   298 		GETCHECK_FIELD();
   299 		CHECK_FIELD_TYPE(UINT64);
   300 		CHECK_FIELD_REPEATED();
   301 		CHECK_REPEATED_ELEMENT(index);
   302 		
   303 		*out = msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
   304 		return true;
   305 	}
   306 
   307 	inline bool SetRepeatedUInt64(const char *pszFieldName, int index, uint64 value)
   308 	{
   309 		GETCHECK_FIELD();
   310 		CHECK_FIELD_TYPE(UINT64);
   311 		CHECK_FIELD_REPEATED();
   312 		CHECK_REPEATED_ELEMENT(index);
   313 		
   314 		msg->GetReflection()->SetRepeatedUInt64(msg, field, index, value);
   315 		return true;
   316 	}
   317 
   318 	inline bool AddUInt64(const char *pszFieldName, uint64 value)
   319 	{
   320 		GETCHECK_FIELD();
   321 		CHECK_FIELD_TYPE(UINT64);
   322 		CHECK_FIELD_REPEATED();
   323 
   324 		msg->GetReflection()->AddUInt32(msg, field, value);
   325 		return true;
   326 	}
   327 
   328 	inline bool GetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 *out)
   329 	{
   330 		GETCHECK_FIELD();
   331 		CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
   332 		CHECK_FIELD_NOT_REPEATED();
   333 
   334 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   335 			*out = (int32)msg->GetReflection()->GetUInt32(*msg, field);
   336 		else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
   337 			*out = msg->GetReflection()->GetInt32(*msg, field);
   338 		else // CPPTYPE_ENUM
   339 			*out = msg->GetReflection()->GetEnum(*msg, field)->number();
   340 
   341 		return true;	
   342 	}
   343 
   344 	inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
   345 	{
   346 		GETCHECK_FIELD();
   347 		CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
   348 		CHECK_FIELD_NOT_REPEATED();
   349 
   350 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   351 		{
   352 			msg->GetReflection()->SetUInt32(msg, field, (uint32)value);
   353 		}
   354 		else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
   355 		{
   356 			msg->GetReflection()->SetInt32(msg, field, value);
   357 		}
   358 		else // CPPTYPE_ENUM
   359 		{
   360 			const protobuf::EnumValueDescriptor *pEnumValue = field->enum_type()->FindValueByNumber(value);
   361 			if (!pEnumValue)
   362 				return false;
   363 
   364 			msg->GetReflection()->SetEnum(msg, field, pEnumValue);
   365 		}
   366 
   367 		return true;
   368 	}
   369 
   370 	inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
   371 	{
   372 		GETCHECK_FIELD();
   373 		CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
   374 		CHECK_FIELD_REPEATED();
   375 		CHECK_REPEATED_ELEMENT(index);
   376 		
   377 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   378 			*out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
   379 		else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
   380 			*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
   381 		else // CPPTYPE_ENUM
   382 			*out = msg->GetReflection()->GetRepeatedEnum(*msg, field, index)->number();
   383 
   384 		return true;
   385 	}
   386 
   387 	inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
   388 	{
   389 		GETCHECK_FIELD();
   390 		CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
   391 		CHECK_FIELD_REPEATED();
   392 		CHECK_REPEATED_ELEMENT(index);
   393 		
   394 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   395 		{
   396 			msg->GetReflection()->SetRepeatedUInt32(msg, field, index, (uint32)value);
   397 		}
   398 		else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
   399 		{
   400 			msg->GetReflection()->SetRepeatedInt32(msg, field, index, value);
   401 		}
   402 		else // CPPTYPE_ENUM
   403 		{
   404 			const protobuf::EnumValueDescriptor *pEnumValue = field->enum_type()->FindValueByNumber(value);
   405 			if (!pEnumValue)
   406 				return false;
   407 
   408 			msg->GetReflection()->SetRepeatedEnum(msg, field, index, pEnumValue);
   409 		}
   410 
   411 		return true;
   412 	}
   413 
   414 	inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
   415 	{
   416 		GETCHECK_FIELD();
   417 		CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
   418 		CHECK_FIELD_REPEATED();
   419 
   420 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   421 		{
   422 			msg->GetReflection()->AddUInt32(msg, field, (uint32)value);
   423 		}
   424 		else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
   425 		{
   426 			msg->GetReflection()->AddInt32(msg, field, value);
   427 		}
   428 		else // CPPTYPE_ENUM
   429 		{
   430 			const protobuf::EnumValueDescriptor *pEnumValue = field->enum_type()->FindValueByNumber(value);
   431 			if (!pEnumValue)
   432 				return false;
   433 
   434 			msg->GetReflection()->AddEnum(msg, field, pEnumValue);
   435 		}
   436 
   437 		return true;
   438 	}
   439 
   440 	inline bool GetBool(const char *pszFieldName, bool *out)
   441 	{
   442 		GETCHECK_FIELD();
   443 		CHECK_FIELD_TYPE(BOOL);
   444 		CHECK_FIELD_NOT_REPEATED();
   445 
   446 		*out = msg->GetReflection()->GetBool(*msg, field);
   447 		return true;	
   448 	}
   449 
   450 	inline bool SetBool(const char *pszFieldName, bool value)
   451 	{
   452 		GETCHECK_FIELD();
   453 		CHECK_FIELD_TYPE(BOOL);
   454 		CHECK_FIELD_NOT_REPEATED();
   455 
   456 		msg->GetReflection()->SetBool(msg, field, value);
   457 		return true;
   458 	}
   459 
   460 	inline bool GetRepeatedBool(const char *pszFieldName, int index, bool *out)
   461 	{
   462 		GETCHECK_FIELD();
   463 		CHECK_FIELD_TYPE(BOOL);
   464 		CHECK_FIELD_REPEATED();
   465 		CHECK_REPEATED_ELEMENT(index);
   466 		
   467 		*out = msg->GetReflection()->GetRepeatedBool(*msg, field, index);
   468 		return true;
   469 	}
   470 
   471 	inline bool SetRepeatedBool(const char *pszFieldName, int index, bool value)
   472 	{
   473 		GETCHECK_FIELD();
   474 		CHECK_FIELD_TYPE(BOOL);
   475 		CHECK_FIELD_REPEATED();
   476 		CHECK_REPEATED_ELEMENT(index);
   477 		
   478 		msg->GetReflection()->SetRepeatedBool(msg, field, index, value);
   479 		return true;
   480 	}
   481 
   482 	inline bool AddBool(const char *pszFieldName, bool value)
   483 	{
   484 		GETCHECK_FIELD();
   485 		CHECK_FIELD_TYPE(BOOL);
   486 		CHECK_FIELD_REPEATED();
   487 
   488 		msg->GetReflection()->AddBool(msg, field, value);
   489 		return true;
   490 	}
   491 
   492 	inline bool GetFloat(const char *pszFieldName, float *out)
   493 	{
   494 		GETCHECK_FIELD();
   495 		CHECK_FIELD_TYPE(FLOAT);
   496 		CHECK_FIELD_NOT_REPEATED();
   497 
   498 		*out = msg->GetReflection()->GetFloat(*msg, field);
   499 		return true;	
   500 	}
   501 
   502 	inline bool SetFloat(const char *pszFieldName, float value)
   503 	{
   504 		GETCHECK_FIELD();
   505 		CHECK_FIELD_TYPE(FLOAT);
   506 		CHECK_FIELD_NOT_REPEATED();
   507 
   508 		msg->GetReflection()->SetFloat(msg, field, value);
   509 		return true;
   510 	}
   511 
   512 	inline bool GetRepeatedFloat(const char *pszFieldName, int index, float *out)
   513 	{
   514 		GETCHECK_FIELD();
   515 		CHECK_FIELD_TYPE(FLOAT);
   516 		CHECK_FIELD_REPEATED();
   517 		CHECK_REPEATED_ELEMENT(index);
   518 		
   519 		*out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
   520 		return true;
   521 	}
   522 
   523 	inline bool SetRepeatedFloat(const char *pszFieldName, int index, float value)
   524 	{
   525 		GETCHECK_FIELD();
   526 		CHECK_FIELD_TYPE(FLOAT);
   527 		CHECK_FIELD_REPEATED();
   528 		CHECK_REPEATED_ELEMENT(index);
   529 		
   530 		msg->GetReflection()->SetRepeatedFloat(msg, field, index, value);
   531 		return true;
   532 	}
   533 
   534 	inline bool AddFloat(const char *pszFieldName, float value)
   535 	{
   536 		GETCHECK_FIELD();
   537 		CHECK_FIELD_TYPE(FLOAT);
   538 		CHECK_FIELD_REPEATED();
   539 
   540 		msg->GetReflection()->AddFloat(msg, field, value);
   541 		return true;
   542 	}
   543 
   544 	inline bool GetDouble(const char *pszFieldName, double *out)
   545 	{
   546 		GETCHECK_FIELD();
   547 		CHECK_FIELD_TYPE(DOUBLE);
   548 		CHECK_FIELD_NOT_REPEATED();
   549 
   550 		*out = msg->GetReflection()->GetDouble(*msg, field);
   551 		return true;	
   552 	}
   553 
   554 	inline bool SetDouble(const char *pszFieldName, double value)
   555 	{
   556 		GETCHECK_FIELD();
   557 		CHECK_FIELD_TYPE(DOUBLE);
   558 		CHECK_FIELD_NOT_REPEATED();
   559 
   560 		msg->GetReflection()->SetDouble(msg, field, value);
   561 		return true;
   562 	}
   563 
   564 	inline bool GetRepeatedDouble(const char *pszFieldName, int index, double *out)
   565 	{
   566 		GETCHECK_FIELD();
   567 		CHECK_FIELD_TYPE(DOUBLE);
   568 		CHECK_FIELD_REPEATED();
   569 		CHECK_REPEATED_ELEMENT(index);
   570 		
   571 		*out = msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
   572 		return true;
   573 	}
   574 
   575 	inline bool SetRepeatedDouble(const char *pszFieldName, int index, double value)
   576 	{
   577 		GETCHECK_FIELD();
   578 		CHECK_FIELD_TYPE(DOUBLE);
   579 		CHECK_FIELD_REPEATED();
   580 		CHECK_REPEATED_ELEMENT(index);
   581 		
   582 		msg->GetReflection()->SetRepeatedDouble(msg, field, index, value);
   583 		return true;
   584 	}
   585 
   586 	inline bool AddDouble(const char *pszFieldName, double value)
   587 	{
   588 		GETCHECK_FIELD();
   589 		CHECK_FIELD_TYPE(DOUBLE);
   590 		CHECK_FIELD_REPEATED();
   591 
   592 		msg->GetReflection()->AddDouble(msg, field, value);
   593 		return true;
   594 	}
   595 
   596 	inline bool GetFloatOrDouble(const char *pszFieldName, float *out)
   597 	{
   598 		GETCHECK_FIELD();
   599 		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   600 		CHECK_FIELD_NOT_REPEATED();
   601 
   602 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   603 			*out = (float)msg->GetReflection()->GetDouble(*msg, field);
   604 		else
   605 			*out = msg->GetReflection()->GetFloat(*msg, field);
   606 
   607 		return true;	
   608 	}
   609 
   610 	inline bool SetFloatOrDouble(const char *pszFieldName, float value)
   611 	{
   612 		GETCHECK_FIELD();
   613 		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   614 		CHECK_FIELD_NOT_REPEATED();
   615 
   616 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   617 			msg->GetReflection()->SetDouble(msg, field, (double)value);
   618 		else
   619 			msg->GetReflection()->SetFloat(msg, field, value);
   620 
   621 		return true;
   622 	}
   623 
   624 	inline bool GetRepeatedFloatOrDouble(const char *pszFieldName, int index, float *out)
   625 	{
   626 		GETCHECK_FIELD();
   627 		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   628 		CHECK_FIELD_REPEATED();
   629 		CHECK_REPEATED_ELEMENT(index);
   630 		
   631 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   632 			*out = (float)msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
   633 		else
   634 			*out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
   635 
   636 		return true;
   637 	}
   638 
   639 	inline bool SetRepeatedFloatOrDouble(const char *pszFieldName, int index, float value)
   640 	{
   641 		GETCHECK_FIELD();
   642 		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   643 		CHECK_FIELD_REPEATED();
   644 		CHECK_REPEATED_ELEMENT(index);
   645 		
   646 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   647 			msg->GetReflection()->SetRepeatedDouble(msg, field, index, (double)value);
   648 		else
   649 			msg->GetReflection()->SetRepeatedFloat(msg, field, index, value);
   650 
   651 		return true;
   652 	}
   653 
   654 	inline bool AddFloatOrDouble(const char *pszFieldName, float value)
   655 	{
   656 		GETCHECK_FIELD();
   657 		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   658 		CHECK_FIELD_REPEATED();
   659 
   660 		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   661 			msg->GetReflection()->AddDouble(msg, field, (double)value);
   662 		else
   663 			msg->GetReflection()->AddFloat(msg, field, value);
   664 
   665 		return true;
   666 	}
   667 
   668 	inline bool GetString(const char *pszFieldName, char *out, int size)
   669 	{
   670 		GETCHECK_FIELD();
   671 		CHECK_FIELD_TYPE(STRING);
   672 		CHECK_FIELD_NOT_REPEATED();
   673 
   674 		std::string scratch;
   675 		strncopy(out, msg->GetReflection()->GetStringReference(*msg, field, &scratch).c_str(), size);
   676 
   677 		return true;	
   678 	}
   679 
   680 	inline bool SetString(const char *pszFieldName, const char *value)
   681 	{
   682 		GETCHECK_FIELD();
   683 		CHECK_FIELD_TYPE(STRING);
   684 		CHECK_FIELD_NOT_REPEATED();
   685 
   686 		msg->GetReflection()->SetString(msg, field, value);
   687 		return true;
   688 	}
   689 
   690 	inline bool GetRepeatedString(const char *pszFieldName, int index, char *out, int size)
   691 	{
   692 		GETCHECK_FIELD();
   693 		CHECK_FIELD_TYPE(STRING);
   694 		CHECK_FIELD_REPEATED();
   695 		CHECK_REPEATED_ELEMENT(index);
   696 		
   697 		std::string scratch;
   698 		strncopy(out, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str(), size);
   699 
   700 		return true;
   701 	}
   702 
   703 	inline bool SetRepeatedString(const char *pszFieldName, int index, const char *value)
   704 	{
   705 		GETCHECK_FIELD();
   706 		CHECK_FIELD_TYPE(STRING);
   707 		CHECK_FIELD_REPEATED();
   708 		CHECK_REPEATED_ELEMENT(index);
   709 		
   710 		msg->GetReflection()->SetRepeatedString(msg, field, index, value);
   711 
   712 		return true;
   713 	}
   714 
   715 	inline bool AddString(const char *pszFieldName, const char *value)
   716 	{
   717 		GETCHECK_FIELD();
   718 		CHECK_FIELD_TYPE(STRING);
   719 		CHECK_FIELD_REPEATED();
   720 
   721 		msg->GetReflection()->AddString(msg, field, value);
   722 		return true;
   723 	}
   724 
   725 	inline bool GetColor(const char *pszFieldName, Color *out)
   726 	{
   727 #if SOURCE_ENGINE != SE_CSGO
   728 		return false;
   729 #else
   730 		GETCHECK_FIELD();
   731 		CHECK_FIELD_TYPE(MESSAGE);
   732 		CHECK_FIELD_NOT_REPEATED();
   733 
   734 		const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetMessage(*msg, field);
   735 		out->SetColor(
   736 			msgRGBA.r(),
   737 			msgRGBA.g(),
   738 			msgRGBA.b(),
   739 			msgRGBA.a()
   740 			);
   741 
   742 		return true;
   743 #endif
   744 	}
   745 
   746 	inline bool SetColor(const char *pszFieldName, const Color &value)
   747 	{
   748 #if SOURCE_ENGINE != SE_CSGO
   749 		return false;
   750 #else
   751 		GETCHECK_FIELD();
   752 		CHECK_FIELD_TYPE(MESSAGE);
   753 		CHECK_FIELD_NOT_REPEATED();
   754 
   755 		CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->MutableMessage(msg, field);
   756 		msgRGBA->set_r(value.r());
   757 		msgRGBA->set_g(value.g());
   758 		msgRGBA->set_b(value.b());
   759 		msgRGBA->set_a(value.a());
   760 
   761 		return true;
   762 #endif
   763 	}
   764 
   765 	inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
   766 	{
   767 #if SOURCE_ENGINE != SE_CSGO
   768 		return false;
   769 #else
   770 		GETCHECK_FIELD();
   771 		CHECK_FIELD_TYPE(MESSAGE);
   772 		CHECK_FIELD_REPEATED();
   773 		CHECK_REPEATED_ELEMENT(index);
   774 
   775 		const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   776 		out->SetColor(
   777 			msgRGBA.r(),
   778 			msgRGBA.g(),
   779 			msgRGBA.b(),
   780 			msgRGBA.a()
   781 			);
   782 
   783 		return true;
   784 #endif
   785 	}
   786 
   787 	inline bool SetRepeatedColor(const char *pszFieldName, int index, const Color &value)
   788 	{
   789 #if SOURCE_ENGINE != SE_CSGO
   790 		return false;
   791 #else
   792 		GETCHECK_FIELD();
   793 		CHECK_FIELD_TYPE(MESSAGE);
   794 		CHECK_FIELD_REPEATED();
   795 		CHECK_REPEATED_ELEMENT(index);
   796 
   797 		CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->MutableRepeatedMessage(msg, field, index);
   798 		msgRGBA->set_r(value.r());
   799 		msgRGBA->set_g(value.g());
   800 		msgRGBA->set_b(value.b());
   801 		msgRGBA->set_a(value.a());
   802 
   803 		return true;
   804 #endif
   805 	}
   806 
   807 	inline bool AddColor(const char *pszFieldName, const Color &value)
   808 	{
   809 #if SOURCE_ENGINE != SE_CSGO
   810 		return false;
   811 #else
   812 		GETCHECK_FIELD();
   813 		CHECK_FIELD_TYPE(MESSAGE);
   814 		CHECK_FIELD_REPEATED();
   815 
   816 		CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->AddMessage(msg, field);
   817 		msgRGBA->set_r(value.r());
   818 		msgRGBA->set_g(value.g());
   819 		msgRGBA->set_b(value.b());
   820 		msgRGBA->set_a(value.a());
   821 
   822 		return true;
   823 #endif
   824 	}
   825 
   826 	inline bool GetVector2D(const char *pszFieldName, Vector2D *out)
   827 	{
   828 		GETCHECK_FIELD();
   829 		CHECK_FIELD_TYPE(MESSAGE);
   830 		CHECK_FIELD_NOT_REPEATED();
   831 
   832 		const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetMessage(*msg, field);
   833 		out->Init(
   834 			msgVec2d.x(),
   835 			msgVec2d.y()
   836 			);
   837 
   838 		return true;
   839 	}
   840 
   841 	inline bool SetVector2D(const char *pszFieldName, Vector2D &vec)
   842 	{
   843 		GETCHECK_FIELD();
   844 		CHECK_FIELD_TYPE(MESSAGE);
   845 		CHECK_FIELD_NOT_REPEATED();
   846 
   847 		CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->MutableMessage(msg, field);
   848 		msgVec2d->set_x(vec.x);
   849 		msgVec2d->set_y(vec.y);
   850 
   851 		return true;
   852 	}
   853 
   854 	inline bool GetRepeatedVector2D(const char *pszFieldName, int index, Vector2D *out)
   855 	{
   856 		GETCHECK_FIELD();
   857 		CHECK_FIELD_TYPE(MESSAGE);
   858 		CHECK_FIELD_REPEATED();
   859 		CHECK_REPEATED_ELEMENT(index);
   860 
   861 		const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   862 		out->Init(
   863 			msgVec2d.x(),
   864 			msgVec2d.y()
   865 			);
   866 
   867 		return true;
   868 	}
   869 
   870 	inline bool SetRepeatedVector2D(const char *pszFieldName, int index, Vector2D &vec)
   871 	{
   872 		GETCHECK_FIELD();
   873 		CHECK_FIELD_TYPE(MESSAGE);
   874 		CHECK_FIELD_REPEATED();
   875 		CHECK_REPEATED_ELEMENT(index);
   876 
   877 		CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->MutableRepeatedMessage(msg, field, index);
   878 		msgVec2d->set_x(vec.x);
   879 		msgVec2d->set_y(vec.y);
   880 
   881 		return true;
   882 	}
   883 
   884 	inline bool AddVector2D(const char *pszFieldName, Vector2D &vec)
   885 	{
   886 		GETCHECK_FIELD();
   887 		CHECK_FIELD_TYPE(MESSAGE);
   888 		CHECK_FIELD_REPEATED();
   889 
   890 		CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->AddMessage(msg, field);
   891 		msgVec2d->set_x(vec.x);
   892 		msgVec2d->set_y(vec.y);
   893 
   894 		return true;
   895 	}
   896 
   897 	inline bool GetVector(const char *pszFieldName, Vector *out)
   898 	{
   899 		GETCHECK_FIELD();
   900 		CHECK_FIELD_TYPE(MESSAGE);
   901 		CHECK_FIELD_NOT_REPEATED();
   902 
   903 		const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetMessage(*msg, field);
   904 		out->Init(
   905 			msgVec.x(),
   906 			msgVec.y(),
   907 			msgVec.z()
   908 			);
   909 
   910 		return true;
   911 	}
   912 
   913 	inline bool SetVector(const char *pszFieldName, Vector &vec)
   914 	{
   915 		GETCHECK_FIELD();
   916 		CHECK_FIELD_TYPE(MESSAGE);
   917 		CHECK_FIELD_NOT_REPEATED();
   918 
   919 		CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->MutableMessage(msg, field);
   920 		msgVec->set_x(vec.x);
   921 		msgVec->set_y(vec.y);
   922 		msgVec->set_z(vec.z);
   923 
   924 		return true;
   925 	}
   926 
   927 	inline bool GetRepeatedVector(const char *pszFieldName, int index, Vector *out)
   928 	{
   929 		GETCHECK_FIELD();
   930 		CHECK_FIELD_TYPE(MESSAGE);
   931 		CHECK_FIELD_REPEATED();
   932 		CHECK_REPEATED_ELEMENT(index);
   933 
   934 		const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   935 		out->Init(
   936 			msgVec.x(),
   937 			msgVec.y(),
   938 			msgVec.z()
   939 			);
   940 
   941 		return true;
   942 	}
   943 
   944 	inline bool SetRepeatedVector(const char *pszFieldName, int index, Vector &vec)
   945 	{
   946 		GETCHECK_FIELD();
   947 		CHECK_FIELD_TYPE(MESSAGE);
   948 		CHECK_FIELD_REPEATED();
   949 		CHECK_REPEATED_ELEMENT(index);
   950 
   951 		CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->MutableRepeatedMessage(msg, field, index);
   952 		msgVec->set_x(vec.x);
   953 		msgVec->set_y(vec.y);
   954 		msgVec->set_z(vec.z);
   955 
   956 		return true;
   957 	}
   958 
   959 	inline bool AddVector(const char *pszFieldName, Vector &vec)
   960 	{
   961 		GETCHECK_FIELD();
   962 		CHECK_FIELD_TYPE(MESSAGE);
   963 		CHECK_FIELD_REPEATED();
   964 
   965 		CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->AddMessage(msg, field);
   966 		msgVec->set_x(vec.x);
   967 		msgVec->set_y(vec.y);
   968 		msgVec->set_z(vec.z);
   969 
   970 		return true;
   971 	}
   972 
   973 	inline bool GetQAngle(const char *pszFieldName, QAngle *out)
   974 	{
   975 		GETCHECK_FIELD();
   976 		CHECK_FIELD_TYPE(MESSAGE);
   977 		CHECK_FIELD_NOT_REPEATED();
   978 
   979 		const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetMessage(*msg, field);
   980 		out->Init(
   981 			msgAng.x(),
   982 			msgAng.y(),
   983 			msgAng.z()
   984 			);
   985 
   986 		return true;
   987 	}
   988 
   989 	inline bool SetQAngle(const char *pszFieldName, QAngle &vec)
   990 	{
   991 		GETCHECK_FIELD();
   992 		CHECK_FIELD_TYPE(MESSAGE);
   993 		CHECK_FIELD_NOT_REPEATED();
   994 
   995 		CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->MutableMessage(msg, field);
   996 		msgAng->set_x(vec.x);
   997 		msgAng->set_y(vec.y);
   998 		msgAng->set_z(vec.z);
   999 
  1000 		return true;
  1001 	}
  1002 
  1003 	inline bool GetRepeatedQAngle(const char *pszFieldName, int index, QAngle *out)
  1004 	{
  1005 		GETCHECK_FIELD();
  1006 		CHECK_FIELD_TYPE(MESSAGE);
  1007 		CHECK_FIELD_REPEATED();
  1008 		CHECK_REPEATED_ELEMENT(index);
  1009 
  1010 		const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
  1011 		out->Init(
  1012 			msgAng.x(),
  1013 			msgAng.y(),
  1014 			msgAng.z()
  1015 			);
  1016 
  1017 		return true;
  1018 	}
  1019 
  1020 	inline bool SetRepeatedQAngle(const char *pszFieldName, int index, QAngle &vec)
  1021 	{
  1022 		GETCHECK_FIELD();
  1023 		CHECK_FIELD_TYPE(MESSAGE);
  1024 		CHECK_FIELD_REPEATED();
  1025 		CHECK_REPEATED_ELEMENT(index);
  1026 
  1027 		CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->MutableRepeatedMessage(msg, field, index);
  1028 		msgAng->set_x(vec.x);
  1029 		msgAng->set_y(vec.y);
  1030 		msgAng->set_z(vec.z);
  1031 
  1032 		return true;
  1033 	}
  1034 
  1035 	inline bool AddQAngle(const char *pszFieldName, QAngle &vec)
  1036 	{
  1037 		GETCHECK_FIELD();
  1038 		CHECK_FIELD_TYPE(MESSAGE);
  1039 		CHECK_FIELD_REPEATED();
  1040 
  1041 		CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->AddMessage(msg, field);
  1042 		msgAng->set_x(vec.x);
  1043 		msgAng->set_y(vec.y);
  1044 		msgAng->set_z(vec.z);
  1045 
  1046 		return true;
  1047 	}
  1048 
  1049 	inline bool GetMessage(const char *pszFieldName, protobuf::Message **message)
  1050 	{
  1051 		GETCHECK_FIELD();
  1052 		CHECK_FIELD_TYPE(MESSAGE);
  1053 		CHECK_FIELD_NOT_REPEATED();
  1054 
  1055 		*message = msg->GetReflection()->MutableMessage(msg, field);
  1056 
  1057 		return true;
  1058 	}
  1059 
  1060 	inline bool GetRepeatedMessage(const char *pszFieldName, int index, const protobuf::Message **message)
  1061 	{
  1062 		GETCHECK_FIELD();
  1063 		CHECK_FIELD_TYPE(MESSAGE);
  1064 		CHECK_FIELD_REPEATED();
  1065 		CHECK_REPEATED_ELEMENT(index);
  1066 
  1067 		const protobuf::Message *m = &msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
  1068 		*message = m;
  1069 
  1070 		return true;
  1071 	}
  1072 
  1073 	inline bool AddMessage(const char *pszFieldName, protobuf::Message **message)
  1074 	{
  1075 		GETCHECK_FIELD();
  1076 		CHECK_FIELD_TYPE(MESSAGE);
  1077 		CHECK_FIELD_REPEATED();
  1078 
  1079 		*message = msg->GetReflection()->AddMessage(msg, field);
  1080 
  1081 		return true;
  1082 	}
  1083 
  1084 	inline int GetRepeatedFieldCount(const char *pszFieldName)
  1085 	{
  1086 		const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
  1087 		if (!field)
  1088 			return -1;
  1089 
  1090 		if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED)
  1091 			return -1;
  1092 
  1093 		return msg->GetReflection()->FieldSize(*msg, field);
  1094 	}
  1095 
  1096 private:
  1097 	protobuf::Message *msg;
  1098 	PBHandleList childHandles;
  1099 };
  1100 
  1101 #endif // _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_