RflySimSDK v3.05
RflySimSDK说明文档
载入中...
搜索中...
未找到
vrpn_Shared.h
1#pragma once
2
3// Horrible hack for old HPUX compiler
4#ifdef hpux
5#ifndef true
6#define bool int
7#define true 1
8#define false 0
9#endif
10#endif
11
12// Definitions needed by several included files.
13#define VRPN_PI (3.14159265358979323846)
14#define VRPN_INCHES_TO_METERS (2.54/100.0)
15#define VRPN_DEGREES_TO_RADIANS (VRPN_PI/180.0)
16
17#include "vrpn_Configure.h" // for VRPN_API
18#include "vrpn_Types.h" // for vrpn_int32, vrpn_float64, etc
19#include "vrpn_Thread.h"
20#include <string.h> // for memcpy(), strncpy()
21#include <stdio.h> // for fprintf()
22#include <new> // for new(std::nothrow)
23
24#if defined(__ANDROID__)
25#include <bitset>
26#endif
27
28// IWYU pragma: no_include <bits/time.h>
29
30// Oct 2000: Sang-Uok changed because vrpn code was compiling but giving
31// runtime errors with cygwin 1.1. I changed the code so it only uses unix
32// code. I had to change includes in various files.
33
34// jan 2000: jeff changing the way sockets are used with cygwin. I made this
35// change because I realized that we were using winsock stuff in some places,
36// and cygwin stuff in others. Discovered this when our code wouldn't compile
37// in cygwin-1.0 (but it did in cygwin-b20.1).
38
39// let's start with a clean slate
40#undef VRPN_USE_WINSOCK_SOCKETS
41
42// Does cygwin use winsock sockets or unix sockets
43//#define VRPN_CYGWIN_USES_WINSOCK_SOCKETS
44
45#if defined(_WIN32) && \
46 (!defined(__CYGWIN__) || defined(VRPN_CYGWIN_USES_WINSOCK_SOCKETS))
47#define VRPN_USE_WINSOCK_SOCKETS
48#define vrpn_SOCKET SOCKET
49#endif
50
51#ifndef VRPN_USE_WINSOCK_SOCKETS
52// On Win32, this constant is defined as ~0 (sockets are unsigned ints)
53#define INVALID_SOCKET -1
54#define vrpn_SOCKET int
55#endif
56
57#if !(defined(_WIN32) && defined(VRPN_USE_WINSOCK_SOCKETS))
58#include <sys/select.h> // for select
59#include <netinet/in.h> // for htonl, htons
60#endif
61
62#ifdef _WIN32_WCE
63#define perror(x) fprintf(stderr, "%s\n", x);
64#endif
65
66// comment from vrpn_Connection.h reads :
67//
68// gethostbyname() fails on SOME Windows NT boxes, but not all,
69// if given an IP octet string rather than a true name.
70// Until we figure out WHY, we have this extra clause in here.
71// It probably wouldn't hurt to enable it for non-NT systems
72// as well.
73#ifdef _WIN32
74#define VRPN_USE_WINDOWS_GETHOSTBYNAME_HACK
75#endif
76
77//--------------------------------------------------------------
78// Timeval defines. These are a bit hairy. The basic problem is
79// that Windows doesn't implement gettimeofday(), nor does it
80// define "struct timezone", although Winsock.h does define
81// "struct timeval". The painful solution has been to define a
82// vrpn_gettimeofday() function that takes a void * as a second
83// argument (the timezone) and have all VRPN code call this function
84// rather than gettimeofday(). On non-WINSOCK implementations,
85// we alias vrpn_gettimeofday() right back to gettimeofday(), so
86// that we are calling the system routine. On Windows, we will
87// be using vrpn_gettimofday(). So far so good, but now user code
88// would like to not have to know the difference under windows, so
89// we have an optional VRPN configuration setting in vrpn_Configure.h
90// that exports vrpn_gettimeofday() as gettimeofday() and also
91// exports a "struct timezone" definition. Yucky, but it works and
92// lets user code use the VRPN one as if it were the system call
93// on Windows.
94
95#if (!defined(VRPN_USE_WINSOCK_SOCKETS))
96#include <sys/time.h> // for timeval, timezone, gettimeofday
97// If we're using std::chrono, then we implement a new
98// vrpn_gettimeofday() on top of it in a platform-independent
99// manner. Otherwise, we just use the system call.
100#ifndef VRPN_USE_STD_CHRONO
101 #define vrpn_gettimeofday gettimeofday
102#else
103 extern "C" VRPN_API int vrpn_gettimeofday(struct timeval *tp,
104 void *tzp = NULL);
105#endif
106#else // winsock sockets
107
108// These are a pair of horrible hacks that instruct Windows include
109// files to (1) not define min() and max() in a way that messes up
110// standard-library calls to them, and (2) avoids pulling in a large
111// number of Windows header files. They are not used directly within
112// the VRPN library, but rather within the Windows include files to
113// change the way they behave.
114
115#ifndef NOMINMAX
116#define NOMINMAX
117#endif
118#ifndef WIN32_LEAN_AND_MEAN
119#define WIN32_LEAN_AND_MEAN
120#endif
121#include <windows.h>
122#ifndef _WIN32_WCE
123#include <sys/timeb.h>
124#endif
125#ifdef VRPN_USE_WINSOCK2
126#include <winsock2.h> // struct timeval is defined here
127#else
128#include <winsock.h> // struct timeval is defined here
129#endif
130
131// Whether or not we export gettimeofday, we declare the
132// vrpn_gettimeofday() function on Windows.
133extern "C" VRPN_API int vrpn_gettimeofday(struct timeval *tp,
134 void *tzp = NULL);
135
136// If compiling under Cygnus Solutions Cygwin then these get defined by
137// including sys/time.h. So, we will manually define only for _WIN32
138// Only do this if the Configure file has set VRPN_EXPORT_GETTIMEOFDAY,
139// so that application code can get at it. All VRPN routines should be
140// calling vrpn_gettimeofday() directly.
141
142#if defined(VRPN_EXPORT_GETTIMEOFDAY)
143
144// manually define this too. _WIN32 sans cygwin doesn't have gettimeofday
145#define gettimeofday vrpn_gettimeofday
146
147#endif
148#endif
149
150//--------------------------------------------------------------
151// vrpn_* timeval utility functions
152
153// IMPORTANT: timevals must be normalized to make any sense
154//
155// * normalized means abs(tv_usec) is less than 1,000,000
156//
157// * TimevalSum and TimevalDiff do not do the right thing if
158// their inputs are not normalized
159//
160// * TimevalScale now normalizes it's results [9/1999 it didn't before]
161
162// make sure tv_usec is less than 1,000,000
163extern VRPN_API struct timeval vrpn_TimevalNormalize(const struct timeval &tv);
164
165extern VRPN_API struct timeval vrpn_TimevalSum(const struct timeval &tv1,
166 const struct timeval &tv2);
167extern VRPN_API struct timeval vrpn_TimevalDiff(const struct timeval &tv1,
168 const struct timeval &tv2);
169extern VRPN_API struct timeval vrpn_TimevalScale(const struct timeval &tv,
170 double scale);
171
173extern VRPN_API unsigned long vrpn_TimevalDuration(struct timeval endT,
174 struct timeval startT);
175
178extern VRPN_API double vrpn_TimevalDurationSeconds(struct timeval endT,
179 struct timeval startT);
180
181extern VRPN_API bool vrpn_TimevalGreater(const struct timeval &tv1,
182 const struct timeval &tv2);
183extern VRPN_API bool vrpn_TimevalEqual(const struct timeval &tv1,
184 const struct timeval &tv2);
185
186extern VRPN_API double vrpn_TimevalMsecs(const struct timeval &tv1);
187
188extern VRPN_API struct timeval vrpn_MsecsTimeval(const double dMsecs);
189extern VRPN_API void vrpn_SleepMsecs(double dMilliSecs);
190
191//--------------------------------------------------------------
192// vrpn_* buffer util functions and endian-ness related
193// definitions and functions.
194
195// xform a double to/from network order -- like htonl and htons
196extern VRPN_API vrpn_float64 vrpn_htond(vrpn_float64 d);
197extern VRPN_API vrpn_float64 vrpn_ntohd(vrpn_float64 d);
198
199// From this we get the variable "vrpn_big_endian" set to true if the machine we
200// are
201// on is big endian and to false if it is little endian. This can be used by
202// custom packing and unpacking code to bypass the buffer and unbuffer routines
203// for cases that have to be particularly fast (like video data). It is also
204// used
205// internally by the vrpn_htond() function.
206
207static const int vrpn_int_data_for_endian_test = 1;
208static const char *vrpn_char_data_for_endian_test =
209 static_cast<const char*>(static_cast<const void *>((&vrpn_int_data_for_endian_test)));
210static const bool vrpn_big_endian = (vrpn_char_data_for_endian_test[0] != 1);
211
212// Read and write strings (not single items).
213extern VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen,
214 const char *string, vrpn_int32 length);
215extern VRPN_API int vrpn_unbuffer(const char **buffer, char *string,
216 vrpn_int32 length);
217
218// Read and write timeval.
219extern VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t);
220extern VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen,
221 const timeval t);
222
223// To read and write the atomic types defined in vrpn_Types, you use the
224// templated
225// buffer and unbuffer routines below. These have the same form as the ones for
226// timeval, but they use types vrpn_int, vrpn_uint, vrpn_int16, vrpn_uint16,
227// vrpn_int32, vrpn_uint32, vrpn_float32, and vrpn_float64.
228
243// Copyright Iowa State University 2011.
244// Distributed under the Boost Software License, Version 1.0.
245// (See accompanying file LICENSE_1_0.txt or copy at
246// http://www.boost.org/LICENSE_1_0.txt)
247
248// Tested in the context of vrpn_server and vrpn_print_devices running between
249// an SGI running Irix 6.5 MIPS 32-bit (big endian) and Mac OSX intel 64-bit
250// (little endian) machine with a NULL tracker and it worked using the SGI
251// repaired commits from 3/17/2012.
252
256 namespace vrpn_detail {
258 template <int TypeSize> struct uint_traits;
259
260 template <> struct uint_traits<1> {
261 typedef vrpn_uint8 type;
262 };
263 template <> struct uint_traits<2> {
264 typedef vrpn_uint16 type;
265 };
266 template <> struct uint_traits<4> {
267 typedef vrpn_uint32 type;
268 };
269 } // end of namespace vrpn_detail
270
272 inline vrpn_uint8 hton(vrpn_uint8 hostval) { return hostval; }
273
275 inline vrpn_uint8 ntoh(vrpn_uint8 netval) { return netval; }
276
278 inline vrpn_uint16 hton(vrpn_uint16 hostval) { return htons(hostval); }
279
281 inline vrpn_uint16 ntoh(vrpn_uint16 netval) { return ntohs(netval); }
282
284 inline vrpn_uint32 hton(vrpn_uint32 hostval) { return htonl(hostval); }
285
287 inline vrpn_uint32 ntoh(vrpn_uint32 netval) { return ntohl(netval); }
288
290 inline vrpn_float64 hton(vrpn_float64 hostval) { return vrpn_htond(hostval); }
291
293 inline vrpn_float64 ntoh(vrpn_float64 netval) { return vrpn_ntohd(netval); }
294
297 template <typename T> inline T hton(T input)
298 {
299 union {
300 T asInput;
301 typename vrpn_detail::uint_traits<sizeof(T)>::type asInt;
302 } inVal, outVal;
303 inVal.asInput = input;
304 outVal.asInt = hton(inVal.asInt);
305 return outVal.asInput;
306 }
307
310 template <typename T> inline T ntoh(T input)
311 {
312 union {
313 T asInput;
314 typename vrpn_detail::uint_traits<sizeof(T)>::type asInt;
315 } inVal, outVal;
316 inVal.asInput = input;
317 outVal.asInt = ntoh(inVal.asInt);
318 return outVal.asInput;
319 }
320} // end of namespace vrpn_byte_order
321
322namespace vrpn_detail {
323 template <typename T> struct remove_const {
324 typedef T type;
325 };
326
327 template <typename T> struct remove_const<const T> {
328 typedef T type;
329 };
330
331 template <bool Condition> struct vrpn_static_assert {
332 };
335 template <> struct vrpn_static_assert<true> {
336 enum { SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE };
337 };
338} // end of namespace vrpn_detail
339
340#ifdef VRPN_USE_STATIC_ASSERTIONS
343#if defined(__GXX_EXPERIMENTAL_CXX0X__) || \
344 (defined(_MSC_VER) && (_MSC_VER >= 1600))
345#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) \
346 static_assert(CONDITION, #MESSAGE)
347#else
348#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) \
349 (void)(::vrpn_detail::vrpn_static_assert<CONDITION>::MESSAGE)
350#endif
351#else
353#include <assert.h>
354#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) assert((CONDITION) && #MESSAGE)
355#endif
356
361template <typename T, typename ByteT>
362static inline T vrpn_unbuffer_from_little_endian(ByteT *&input)
363{
364 using namespace vrpn_byte_order;
365
366 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
367
369 union {
370 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
371 T typed;
372 } value;
373
375 for (unsigned int i = 0, j = sizeof(T) - 1; i < sizeof(T); ++i, --j) {
376 value.bytes[i] = input[j];
377 }
378
380 input += sizeof(T);
381
383 return ntoh(value.typed);
384}
385
390template <typename T, typename ByteT> inline T vrpn_unbuffer(ByteT *&input)
391{
392 using namespace vrpn_byte_order;
393
394 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
395
397 union {
398 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
399 T typed;
400 } value;
401
403 memcpy(value.bytes, input, sizeof(T));
404
406 input += sizeof(T);
407
409 return ntoh(value.typed);
410}
411
416template <typename T, typename ByteT>
417inline int vrpn_buffer_to_little_endian(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
418{
419 using namespace vrpn_byte_order;
420
421 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
422
423 if ((insertPt == NULL) || (buflen == NULL)) {
424 fprintf(stderr, "vrpn_buffer: NULL pointer\n");
425 return -1;
426 }
427
428 if (sizeof(T) > static_cast<size_t>(*buflen)) {
429 fprintf(stderr, "vrpn_buffer: buffer not large enough\n");
430 return -1;
431 }
432
434 union {
435 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
436 T typed;
437 } value;
438
440 value.typed = hton(inVal);
441
443 for (unsigned int i = 0, j = sizeof(T) - 1; i < sizeof(T); ++i, --j) {
444 (*insertPt)[i] = value.bytes[j];
445 }
446
448 *insertPt += sizeof(T);
450 *buflen -= sizeof(T);
451
452 return 0;
453}
454
459template <typename T, typename ByteT>
460inline int vrpn_buffer(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
461{
462 using namespace vrpn_byte_order;
463
464 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
465
466 if ((insertPt == NULL) || (buflen == NULL)) {
467 fprintf(stderr, "vrpn_buffer: NULL pointer\n");
468 return -1;
469 }
470
471 if (sizeof(T) > static_cast<size_t>(*buflen)) {
472 fprintf(stderr, "vrpn_buffer: buffer not large enough\n");
473 return -1;
474 }
475
477 union {
478 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
479 T typed;
480 } value;
481
483 value.typed = hton(inVal);
484
486 memcpy(*insertPt, value.bytes, sizeof(T));
487
489 *insertPt += sizeof(T);
491 *buflen -= sizeof(T);
492
493 return 0;
494}
495
496template <typename T, typename ByteT>
497inline int vrpn_unbuffer(ByteT **input, T *lvalue)
498{
499 *lvalue = ::vrpn_unbuffer<T, ByteT>(*input);
500 return 0;
501}
502
503// Returns true if tests work and false if they do not.
504extern bool vrpn_test_pack_unpack(void);
505
510inline char *vrpn_strncpynull(char* dst, const char* src, size_t size)
511{
512 if (size > 0) {
513 size_t i;
514 for (i = 0; i < size - 1 && src[i]; i++) {
515 dst[i] = src[i];
516 }
517 dst[i] = '\0';
518 }
519 return dst;
520}
521
527
528template <size_t charCount> void vrpn_strcpy(char (&to)[charCount], const char* pSrc)
529{
530 // Copy the string - don't copy too many bytes.
531#ifdef _WIN32
532 strncpy_s(to, pSrc, charCount);
533#else
534 strncpy(to, pSrc, charCount - 1);
535#endif
536 // Ensure null-termination.
537 to[charCount - 1] = 0;
538}
539
540// This is a replacement for std::vector that implements the subset of
541// features needed for the VRPN objects that use it.
542// We can't use std::vector because:
543// (1) We need to continue to support compilers from before it
544// was defined.
545// (2) Phantom force-feedback drivers include <vector.h>, and the same
546// code that uses it cannot include <vector>; they are link-time
547// incompatible.
548// We call this structure vrpn_vector rather than vrpn::vector to avoid
549// having an application end up using it by mistake when they mean
550// std::vector.
551
552template <class T> class vrpn_vector {
553public:
554 typedef size_t size_type;
555 typedef T* iterator;
556 typedef const T* const_iterator;
557 vrpn_vector() : m_size(0), m_data(0), m_allocated(0) {};
558 vrpn_vector(size_type s) : m_size(0), m_data(0), m_allocated(0) {
559 m_data = new T[s];
560 m_size = m_allocated = s;
561 }
562 vrpn_vector( const vrpn_vector &from )
563 : m_size(from.size()), m_data(0), m_allocated(from.size()) {
564 m_data = new T[m_size];
565 for (size_t i = 0; i < m_size; i++) {
566 m_data[i] = from.m_data[i];
567 }
568 }
569 template< class InputIt >
570 vrpn_vector( InputIt first, InputIt last ) : m_size(0), m_data(0), m_allocated(0) {
571 for (InputIt it = first; it != last; ++it) {
572 push_back(*it);
573 }
574 }
575 ~vrpn_vector() {
576 delete [] m_data;
577 m_size = m_allocated = 0;
578 }
579 vrpn_vector &operator =(const vrpn_vector& from)
580 {
581 delete[] m_data;
582 m_size = m_allocated = from.size();
583 m_data = new T[m_size];
584 for (size_t i = 0; i < m_size; i++) {
585 m_data[i] = from.m_data[i];
586 }
587 return *this;
588 }
589 T* data() { return m_data; }
590 size_type size() const { return m_size; }
591 bool empty() const { return m_size == 0; }
592 void resize(size_type s) {
593 // If we already have enough allocated space, set the size
594 // and leave the allocated size alone.
595 if (s <= m_allocated) {
596 m_size = s;
597 } else {
598 // We do not have enough space, so we need to allocate a new buffer
599 // and then copy the old buffer and then delete the original buffer.
600 T* newData = new T[s];
601 for (size_t i = 0; i < m_size; i++) {
602 newData[i] = m_data[i];
603 }
604 delete [] m_data;
605 m_data = newData;
606 m_size = m_allocated = s;
607 }
608 }
609 void push_back (const T& val) {
610 resize(m_size + 1);
611 m_data[m_size-1] = val;
612 }
613 T& front() {
614 return m_data[0];
615 }
616 T& back() {
617 return m_data[m_size-1];
618 }
619 T& operator[]( size_type pos ) {
620 return m_data[pos];
621 }
622 const T& operator[]( size_type pos ) const {
623 return m_data[pos];
624 }
625 void assign( size_type count, const T& value ) {
626 resize(count);
627 for (size_type i = 0; i < size(); i++) {
628 m_data[i] = value;
629 }
630 }
631 void clear() { m_size = 0; }
632 template< class InputIt >
633 void assign( InputIt first, InputIt last ) {
634 clear();
635 for (InputIt it = first; it != last; it++) {
636 push_back(*it);
637 }
638 }
639 iterator begin() { return m_data; }
640 const_iterator begin() const { return m_data; }
641 iterator end() {
642 if (m_size != 0) {
643 return &m_data[m_size];
644 } else {
645 return 0;
646 }
647 }
648 const_iterator end() const {
649 if (m_size != 0) {
650 return &m_data[m_size];
651 } else {
652 return 0;
653 }
654 }
655private:
656 size_type m_size, m_allocated;
657 T* m_data;
658};
659
660// Returns true if tests work and false if they do not.
661extern bool vrpn_test_vrpn_vector(void);
定义 vrpn_Shared.h:552
Internal header providing unbuffering facilities for a number of types.
定义 vrpn_Shared.h:255
vrpn_uint8 hton(vrpn_uint8 hostval)
host to network byte order for 8-bit uints is a no-op
定义 vrpn_Shared.h:272
vrpn_uint8 ntoh(vrpn_uint8 netval)
network to host byte order for 8-bit uints is a no-op
定义 vrpn_Shared.h:275
Traits class to get the uint type of a given size
定义 vrpn_Shared.h:258
定义 vrpn_Shared.h:323
定义 vrpn_Shared.h:331
Header containing vrpn_Thread, vrpn_Semaphore (formerly in vrpn_Shared.h), as well as a lock-guard cl...