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