3 * =============================================================================
5 * Copyright (C) 2013 AlliedModders LLC. All rights reserved.
6 * =============================================================================
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.
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
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/>.
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>.
32 #ifndef _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
33 #define _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
36 #include <google/protobuf/descriptor.h>
38 #define GETCHECK_FIELD() \
39 const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
45 #define CHECK_FIELD_TYPE(type) \
46 if (field->cpp_type() != protobuf::FieldDescriptor::CPPTYPE_##type) \
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) \
59 #define CHECK_FIELD_REPEATED() \
60 if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \
65 #define CHECK_FIELD_NOT_REPEATED() \
66 if (field->label() == protobuf::FieldDescriptor::LABEL_REPEATED) \
71 #define CHECK_REPEATED_ELEMENT(idx) \
72 int elemCount = msg->GetReflection()->FieldSize(*msg, field); \
73 if (elemCount == 0 || idx >= elemCount || idx <= 0) \
78 typedef List<Handle_t> PBHandleList;
80 class SMProtobufMessage
83 SMProtobufMessage( protobuf::Message *message )
90 PBHandleList::iterator iter = childHandles.begin();
91 while (iter != childHandles.end())
93 Handle_t &hndl = (*iter);
95 sec.pIdentity = g_pCoreIdent;
96 g_HandleSys.FreeHandle(hndl, &sec);
97 iter = childHandles.erase(iter);
101 inline void AddChildHandle(Handle_t hndl)
103 childHandles.push_back(hndl);
106 inline protobuf::Message *GetProtobufMessage()
111 inline bool GetInt32(const char *pszFieldName, int32 *out)
114 CHECK_FIELD_TYPE(INT32);
115 CHECK_FIELD_NOT_REPEATED();
117 *out = msg->GetReflection()->GetInt32(*msg, field);
121 inline bool SetInt32(const char *pszFieldName, int32 value)
124 CHECK_FIELD_TYPE(INT32);
125 CHECK_FIELD_NOT_REPEATED();
127 msg->GetReflection()->SetInt32(msg, field, value);
131 inline bool GetRepeatedInt32(const char *pszFieldName, int index, int32 *out)
134 CHECK_FIELD_TYPE(INT32);
135 CHECK_FIELD_REPEATED();
136 CHECK_REPEATED_ELEMENT(index);
138 *out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
142 inline bool AddInt32(const char *pszFieldName, int32 value)
145 CHECK_FIELD_TYPE(INT32);
146 CHECK_FIELD_REPEATED();
148 msg->GetReflection()->AddInt32(msg, field, value);
152 inline bool GetInt64(const char *pszFieldName, int64 *out)
155 CHECK_FIELD_TYPE(INT64);
156 CHECK_FIELD_NOT_REPEATED();
158 *out = msg->GetReflection()->GetInt64(*msg, field);
162 inline bool SetInt64(const char *pszFieldName, int64 value)
165 CHECK_FIELD_TYPE(INT64);
166 CHECK_FIELD_NOT_REPEATED();
168 msg->GetReflection()->SetInt64(msg, field, value);
172 inline bool GetRepeatedInt64(const char *pszFieldName, int index, int64 *out)
175 CHECK_FIELD_TYPE(INT64);
176 CHECK_FIELD_REPEATED();
177 CHECK_REPEATED_ELEMENT(index);
179 *out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
183 inline bool AddInt64(const char *pszFieldName, int64 value)
186 CHECK_FIELD_TYPE(INT64);
187 CHECK_FIELD_REPEATED();
189 msg->GetReflection()->AddInt64(msg, field, value);
193 inline bool GetUInt32(const char *pszFieldName, uint32 *out)
196 CHECK_FIELD_TYPE(UINT32);
197 CHECK_FIELD_NOT_REPEATED();
199 *out = msg->GetReflection()->GetUInt32(*msg, field);
203 inline bool SetUInt32(const char *pszFieldName, uint32 value)
206 CHECK_FIELD_TYPE(UINT32);
207 CHECK_FIELD_NOT_REPEATED();
209 msg->GetReflection()->SetUInt32(msg, field, value);
213 inline bool GetRepeatedUInt32(const char *pszFieldName, int index, uint32 *out)
216 CHECK_FIELD_TYPE(UINT32);
217 CHECK_FIELD_REPEATED();
218 CHECK_REPEATED_ELEMENT(index);
220 *out = msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
224 inline bool AddUInt32(const char *pszFieldName, uint32 value)
227 CHECK_FIELD_TYPE(UINT32);
228 CHECK_FIELD_REPEATED();
230 msg->GetReflection()->AddUInt32(msg, field, value);
234 inline bool GetUInt64(const char *pszFieldName, uint64 *out)
237 CHECK_FIELD_TYPE(UINT64);
238 CHECK_FIELD_NOT_REPEATED();
240 *out = msg->GetReflection()->GetUInt64(*msg, field);
244 inline bool SetUInt64(const char *pszFieldName, uint64 value)
247 CHECK_FIELD_TYPE(UINT64);
248 CHECK_FIELD_NOT_REPEATED();
250 msg->GetReflection()->SetUInt64(msg, field, value);
254 inline bool GetRepeatedUInt64(const char *pszFieldName, int index, uint64 *out)
257 CHECK_FIELD_TYPE(UINT64);
258 CHECK_FIELD_REPEATED();
259 CHECK_REPEATED_ELEMENT(index);
261 *out = msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
265 inline bool AddUInt64(const char *pszFieldName, uint64 value)
268 CHECK_FIELD_TYPE(UINT64);
269 CHECK_FIELD_REPEATED();
271 msg->GetReflection()->AddUInt32(msg, field, value);
275 inline bool GetInt32OrUnsigned(const char *pszFieldName, int32 *out)
278 CHECK_FIELD_TYPE2(INT32, UINT32);
279 CHECK_FIELD_NOT_REPEATED();
281 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
282 *out = (int32)msg->GetReflection()->GetUInt32(*msg, field);
284 *out = msg->GetReflection()->GetInt32(*msg, field);
289 inline bool SetInt32OrUnsigned(const char *pszFieldName, int32 value)
292 CHECK_FIELD_TYPE2(INT32, UINT32);
293 CHECK_FIELD_NOT_REPEATED();
295 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
296 msg->GetReflection()->SetUInt32(msg, field, (uint32)value);
298 msg->GetReflection()->SetInt32(msg, field, value);
303 inline bool GetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 *out)
306 CHECK_FIELD_TYPE2(INT32, UINT32);
307 CHECK_FIELD_REPEATED();
308 CHECK_REPEATED_ELEMENT(index);
310 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
311 *out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
313 *out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
318 inline bool AddInt32OrUnsigned(const char *pszFieldName, int32 value)
321 CHECK_FIELD_TYPE2(INT32, UINT32);
322 CHECK_FIELD_REPEATED();
324 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
325 msg->GetReflection()->AddUInt32(msg, field, (uint32)value);
327 msg->GetReflection()->AddInt32(msg, field, value);
332 inline bool GetBool(const char *pszFieldName, bool *out)
335 CHECK_FIELD_TYPE(BOOL);
336 CHECK_FIELD_NOT_REPEATED();
338 *out = msg->GetReflection()->GetBool(*msg, field);
342 inline bool SetBool(const char *pszFieldName, bool value)
345 CHECK_FIELD_TYPE(BOOL);
346 CHECK_FIELD_NOT_REPEATED();
348 msg->GetReflection()->SetBool(msg, field, value);
352 inline bool GetRepeatedBool(const char *pszFieldName, int index, bool *out)
355 CHECK_FIELD_TYPE(BOOL);
356 CHECK_FIELD_REPEATED();
357 CHECK_REPEATED_ELEMENT(index);
359 *out = msg->GetReflection()->GetRepeatedBool(*msg, field, index);
363 inline bool AddBool(const char *pszFieldName, bool value)
366 CHECK_FIELD_TYPE(BOOL);
367 CHECK_FIELD_REPEATED();
369 msg->GetReflection()->AddBool(msg, field, value);
373 inline bool GetFloat(const char *pszFieldName, float *out)
376 CHECK_FIELD_TYPE(FLOAT);
377 CHECK_FIELD_NOT_REPEATED();
379 *out = msg->GetReflection()->GetFloat(*msg, field);
383 inline bool SetFloat(const char *pszFieldName, float value)
386 CHECK_FIELD_TYPE(FLOAT);
387 CHECK_FIELD_NOT_REPEATED();
389 msg->GetReflection()->SetFloat(msg, field, value);
393 inline bool GetRepeatedFloat(const char *pszFieldName, int index, float *out)
396 CHECK_FIELD_TYPE(FLOAT);
397 CHECK_FIELD_REPEATED();
398 CHECK_REPEATED_ELEMENT(index);
400 *out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
404 inline bool AddFloat(const char *pszFieldName, float value)
407 CHECK_FIELD_TYPE(FLOAT);
408 CHECK_FIELD_REPEATED();
410 msg->GetReflection()->AddFloat(msg, field, value);
414 inline bool GetDouble(const char *pszFieldName, double *out)
417 CHECK_FIELD_TYPE(DOUBLE);
418 CHECK_FIELD_NOT_REPEATED();
420 *out = msg->GetReflection()->GetDouble(*msg, field);
424 inline bool SetDouble(const char *pszFieldName, double value)
427 CHECK_FIELD_TYPE(DOUBLE);
428 CHECK_FIELD_NOT_REPEATED();
430 msg->GetReflection()->SetDouble(msg, field, value);
434 inline bool GetRepeatedDouble(const char *pszFieldName, int index, double *out)
437 CHECK_FIELD_TYPE(DOUBLE);
438 CHECK_FIELD_REPEATED();
439 CHECK_REPEATED_ELEMENT(index);
441 *out = msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
445 inline bool AddDouble(const char *pszFieldName, double value)
448 CHECK_FIELD_TYPE(DOUBLE);
449 CHECK_FIELD_REPEATED();
451 msg->GetReflection()->AddDouble(msg, field, value);
455 inline bool GetFloatOrDouble(const char *pszFieldName, float *out)
458 CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
459 CHECK_FIELD_NOT_REPEATED();
461 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
462 *out = (float)msg->GetReflection()->GetDouble(*msg, field);
464 *out = msg->GetReflection()->GetFloat(*msg, field);
469 inline bool SetFloatOrDouble(const char *pszFieldName, float value)
472 CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
473 CHECK_FIELD_NOT_REPEATED();
475 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
476 msg->GetReflection()->SetDouble(msg, field, (double)value);
478 msg->GetReflection()->SetFloat(msg, field, value);
483 inline bool GetRepeatedFloatOrDouble(const char *pszFieldName, int index, float *out)
486 CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
487 CHECK_FIELD_REPEATED();
488 CHECK_REPEATED_ELEMENT(index);
490 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
491 *out = (float)msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
493 *out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
498 inline bool AddFloatOrDouble(const char *pszFieldName, float value)
501 CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
502 CHECK_FIELD_REPEATED();
504 if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
505 msg->GetReflection()->AddDouble(msg, field, (double)value);
507 msg->GetReflection()->AddFloat(msg, field, value);
512 inline bool GetString(const char *pszFieldName, char *out, int size)
515 CHECK_FIELD_TYPE(STRING);
516 CHECK_FIELD_NOT_REPEATED();
519 strncopy(out, msg->GetReflection()->GetStringReference(*msg, field, &buffer).c_str(), size);
524 inline bool SetString(const char *pszFieldName, const char *value)
527 CHECK_FIELD_TYPE(STRING);
528 CHECK_FIELD_NOT_REPEATED();
530 msg->GetReflection()->SetString(msg, field, value);
534 inline bool GetRepeatedString(const char *pszFieldName, int index, char *out, int size)
537 CHECK_FIELD_TYPE(STRING);
538 CHECK_FIELD_REPEATED();
539 CHECK_REPEATED_ELEMENT(index);
542 strncopy(out, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str(), size);
547 inline bool AddString(const char *pszFieldName, const char *value)
550 CHECK_FIELD_TYPE(STRING);
551 CHECK_FIELD_REPEATED();
553 msg->GetReflection()->AddString(msg, field, value);
557 inline bool GetColor(const char *pszFieldName, Color *out)
560 CHECK_FIELD_TYPE(MESSAGE);
561 CHECK_FIELD_NOT_REPEATED();
563 const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetMessage(*msg, field);
574 inline bool SetColor(const char *pszFieldName, const Color &value)
577 CHECK_FIELD_TYPE(MESSAGE);
578 CHECK_FIELD_NOT_REPEATED();
580 CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->MutableMessage(msg, field);
581 msgRGBA->set_r(value.r());
582 msgRGBA->set_g(value.g());
583 msgRGBA->set_b(value.b());
584 msgRGBA->set_a(value.a());
589 inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
592 CHECK_FIELD_TYPE(MESSAGE);
593 CHECK_FIELD_REPEATED();
594 CHECK_REPEATED_ELEMENT(index);
596 const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
607 inline bool AddColor(const char *pszFieldName, const Color &value)
610 CHECK_FIELD_TYPE(MESSAGE);
611 CHECK_FIELD_REPEATED();
613 CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->AddMessage(msg, field);
614 msgRGBA->set_r(value.r());
615 msgRGBA->set_g(value.g());
616 msgRGBA->set_b(value.b());
617 msgRGBA->set_a(value.a());
622 inline bool GetVector2D(const char *pszFieldName, Vector2D *out)
625 CHECK_FIELD_TYPE(MESSAGE);
626 CHECK_FIELD_NOT_REPEATED();
628 const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetMessage(*msg, field);
637 inline bool SetVector2D(const char *pszFieldName, Vector2D &vec)
640 CHECK_FIELD_TYPE(MESSAGE);
641 CHECK_FIELD_NOT_REPEATED();
643 CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->MutableMessage(msg, field);
644 msgVec2d->set_x(vec.x);
645 msgVec2d->set_y(vec.y);
650 inline bool GetRepeatedVector2D(const char *pszFieldName, int index, Vector2D *out)
653 CHECK_FIELD_TYPE(MESSAGE);
654 CHECK_FIELD_REPEATED();
655 CHECK_REPEATED_ELEMENT(index);
657 const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
666 inline bool AddVector2D(const char *pszFieldName, Vector2D &vec)
669 CHECK_FIELD_TYPE(MESSAGE);
670 CHECK_FIELD_REPEATED();
672 CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->AddMessage(msg, field);
673 msgVec2d->set_x(vec.x);
674 msgVec2d->set_y(vec.y);
679 inline bool GetVector(const char *pszFieldName, Vector *out)
682 CHECK_FIELD_TYPE(MESSAGE);
683 CHECK_FIELD_NOT_REPEATED();
685 const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetMessage(*msg, field);
695 inline bool SetVector(const char *pszFieldName, Vector &vec)
698 CHECK_FIELD_TYPE(MESSAGE);
699 CHECK_FIELD_NOT_REPEATED();
701 CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->MutableMessage(msg, field);
702 msgVec->set_x(vec.x);
703 msgVec->set_y(vec.y);
704 msgVec->set_z(vec.z);
709 inline bool GetRepeatedVector(const char *pszFieldName, int index, Vector *out)
712 CHECK_FIELD_TYPE(MESSAGE);
713 CHECK_FIELD_REPEATED();
714 CHECK_REPEATED_ELEMENT(index);
716 const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
726 inline bool AddVector(const char *pszFieldName, Vector &vec)
729 CHECK_FIELD_TYPE(MESSAGE);
730 CHECK_FIELD_REPEATED();
732 CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->AddMessage(msg, field);
733 msgVec->set_x(vec.x);
734 msgVec->set_y(vec.y);
735 msgVec->set_z(vec.z);
740 inline bool GetQAngle(const char *pszFieldName, QAngle *out)
743 CHECK_FIELD_TYPE(MESSAGE);
744 CHECK_FIELD_NOT_REPEATED();
746 const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetMessage(*msg, field);
756 inline bool SetQAngle(const char *pszFieldName, QAngle &vec)
759 CHECK_FIELD_TYPE(MESSAGE);
760 CHECK_FIELD_NOT_REPEATED();
762 CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->MutableMessage(msg, field);
763 msgAng->set_x(vec.x);
764 msgAng->set_y(vec.y);
765 msgAng->set_z(vec.z);
770 inline bool GetRepeatedQAngle(const char *pszFieldName, int index, QAngle *out)
773 CHECK_FIELD_TYPE(MESSAGE);
774 CHECK_FIELD_REPEATED();
775 CHECK_REPEATED_ELEMENT(index);
777 const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
787 inline bool AddQAngle(const char *pszFieldName, QAngle &vec)
790 CHECK_FIELD_TYPE(MESSAGE);
791 CHECK_FIELD_REPEATED();
793 CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->AddMessage(msg, field);
794 msgAng->set_x(vec.x);
795 msgAng->set_y(vec.y);
796 msgAng->set_z(vec.z);
801 inline bool GetMessage(const char *pszFieldName, protobuf::Message **message)
804 CHECK_FIELD_TYPE(MESSAGE);
805 CHECK_FIELD_NOT_REPEATED();
807 *message = msg->GetReflection()->MutableMessage(msg, field);
812 inline bool GetRepeatedMessage(const char *pszFieldName, int index, const protobuf::Message **message)
815 CHECK_FIELD_TYPE(MESSAGE);
816 CHECK_FIELD_REPEATED();
817 CHECK_REPEATED_ELEMENT(index);
819 const protobuf::Message *m = &msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
825 inline bool AddMessage(const char *pszFieldName, protobuf::Message **message)
828 CHECK_FIELD_TYPE(MESSAGE);
829 CHECK_FIELD_REPEATED();
831 *message = msg->GetReflection()->AddMessage(msg, field);
836 inline int GetRepeatedFieldCount(const char *pszFieldName)
838 const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
842 if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED)
845 return msg->GetReflection()->FieldSize(*msg, field);
849 protobuf::Message *msg;
850 PBHandleList childHandles;
853 #endif // _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_