Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/util/Serialise.h @ 7687

Last change on this file since 7687 was 7163, checked in by dafrick, 14 years ago

Merged presentation3 branch into trunk.

  • Property svn:eol-style set to native
File size: 22.2 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Oliver Scheuss
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @brief Functions to serialise most of the types/classed used in Orxonox
32*/
33
34#ifndef _Serialise_H__
35#define _Serialise_H__
36
37#include "UtilPrereqs.h"
38
39#include <cstring>
40#include <set>
41#include "Math.h"
42#include "mbool.h"
43
44namespace orxonox{
45
46    /** @brief returns the size of the variable in a datastream */
47    template <class T> inline uint32_t returnSize( const T& variable );
48    /** @brief loads the value of a variable out of the bytestream and increases the mem pointer */
49    template <class T> inline void loadAndIncrease( const T& variable, uint8_t*& mem );
50    /** @brief saves the value of a variable into the bytestream and increases the mem pointer */
51    template <class T> inline void saveAndIncrease( const T& variable, uint8_t*& mem );
52    /** @brief checks whether the variable of type T is the same as in the bytestream */
53    template <class T> inline bool checkEquality( const T& variable, uint8_t* mem );
54
55 
56  // =========== char*
57   
58  inline uint32_t returnSize( char*& variable )
59  {
60    return strlen(variable)+1;
61  }
62     
63  inline void saveAndIncrease( char*& variable, uint8_t*& mem )
64  {
65    strcpy((char*)mem, variable);
66    mem += returnSize(variable);
67  }
68       
69  inline void loadAndIncrease( char*& variable, uint8_t*& mem )
70  {
71    if( variable )
72      delete variable;
73    uint32_t len = strlen((char*)mem)+1;
74    variable = new char[len];
75    strcpy((char*)variable, (char*)mem);
76    mem += len;
77  }
78         
79  inline bool checkEquality( char*& variable, uint8_t* mem )
80  {
81    return strcmp(variable, (char*)mem)==0;
82  }
83   
84// =================== Template specialisation stuff =============
85
86// =========== bool
87
88    template <> inline uint32_t returnSize( const bool& variable )
89    {
90        return sizeof(uint8_t);
91    }
92
93    template <> inline void loadAndIncrease( const bool& variable, uint8_t*& mem )
94    {
95        *(uint8_t*)( &variable ) = *static_cast<uint8_t*>(mem);
96        mem += returnSize( variable );
97    }
98
99    template <> inline void saveAndIncrease( const bool& variable, uint8_t*& mem )
100    {
101        *static_cast<uint8_t*>(mem) = *(uint8_t*)( &variable );
102        mem += returnSize( variable );
103    }
104
105    template <> inline bool checkEquality( const bool& variable, uint8_t* mem )
106    {
107        return *static_cast<uint8_t*>(mem) == *(uint8_t*)( &variable );
108    }
109
110// =========== char
111
112    template <> inline uint32_t returnSize( const char& variable )
113    {
114        return sizeof(uint8_t);
115    }
116
117    template <> inline void loadAndIncrease( const char& variable, uint8_t*& mem )
118    {
119        *(uint8_t*)( &variable ) = *static_cast<uint8_t*>(mem);
120        mem += returnSize( variable );
121    }
122
123    template <> inline void saveAndIncrease( const char& variable, uint8_t*& mem )
124    {
125        *static_cast<uint8_t*>(mem) = *(uint8_t*)( &variable );
126        mem += returnSize( variable );
127    }
128
129    template <> inline bool checkEquality( const char& variable, uint8_t* mem )
130    {
131        return *static_cast<uint8_t*>(mem) == *(uint8_t*)( &variable );
132    }
133
134// =========== unsigned char
135
136    template <> inline uint32_t returnSize( const unsigned char& variable )
137    {
138        return sizeof(uint8_t);
139    }
140
141    template <> inline void loadAndIncrease( const unsigned char& variable, uint8_t*& mem )
142    {
143        *(uint8_t*)( &variable ) = *static_cast<uint8_t*>(mem);
144        mem += returnSize( variable );
145    }
146
147    template <> inline void saveAndIncrease( const unsigned char& variable, uint8_t*& mem )
148    {
149        *static_cast<uint8_t*>(mem) = *(uint8_t*)( &variable );
150        mem += returnSize( variable );
151    }
152
153    template <> inline bool checkEquality( const unsigned char& variable, uint8_t* mem )
154    {
155        return *static_cast<uint8_t*>(mem) == *(uint8_t*)( &variable );
156    }
157
158// =========== short
159
160    template <> inline uint32_t returnSize( const short& variable )
161    {
162        return sizeof(int16_t);
163    }
164
165    template <> inline void loadAndIncrease( const short& variable, uint8_t*& mem )
166    {
167        *(short*)( &variable ) = *(int16_t*)(mem);
168        mem += returnSize( variable );
169    }
170
171    template <> inline void saveAndIncrease( const short& variable, uint8_t*& mem )
172    {
173        *(int16_t*)(mem) = variable;
174        mem += returnSize( variable );
175    }
176
177    template <> inline bool checkEquality( const short& variable, uint8_t* mem )
178    {
179        return *(int16_t*)(mem) == static_cast<int16_t>(variable);
180    }
181
182// =========== unsigned short
183
184    template <> inline uint32_t returnSize( const unsigned short& variable )
185    {
186        return sizeof(uint16_t);
187    }
188
189    template <> inline void loadAndIncrease( const unsigned short& variable, uint8_t*& mem )
190    {
191        *(unsigned short*)( &variable ) = *(uint16_t*)(mem);
192        mem += returnSize( variable );
193    }
194
195    template <> inline void saveAndIncrease( const unsigned short& variable, uint8_t*& mem )
196    {
197        *(uint16_t*)(mem) = variable;
198        mem += returnSize( variable );
199    }
200
201    template <> inline bool checkEquality( const unsigned short& variable, uint8_t* mem )
202    {
203        return *(uint16_t*)(mem) == variable;
204    }
205
206// =========== int
207
208    template <> inline uint32_t returnSize( const int& variable )
209    {
210        return sizeof(int32_t);
211    }
212
213    template <> inline void loadAndIncrease( const int& variable, uint8_t*& mem )
214    {
215        *(int *)( &variable ) = *(int32_t*)(mem);
216        mem += returnSize( variable );
217    }
218
219    template <> inline void saveAndIncrease( const int& variable, uint8_t*& mem )
220    {
221        *(int32_t*)(mem) = variable;
222        mem += returnSize( variable );
223    }
224
225    template <> inline bool checkEquality( const int& variable, uint8_t* mem )
226    {
227        return *(int32_t*)(mem) == variable;
228    }
229
230// =========== unsigned int
231
232    template <> inline uint32_t returnSize( const unsigned int& variable )
233    {
234        return sizeof(uint32_t);
235    }
236
237    template <> inline void loadAndIncrease( const unsigned int& variable, uint8_t*& mem )
238    {
239        *(unsigned int*)( &variable ) = *(uint32_t*)(mem);
240        mem += returnSize( variable );
241    }
242
243    template <> inline void saveAndIncrease( const unsigned int& variable, uint8_t*& mem )
244    {
245        *(uint32_t*)(mem) = variable;
246        mem += returnSize( variable );
247    }
248
249    template <> inline bool checkEquality( const unsigned int& variable, uint8_t* mem )
250    {
251        return *(uint32_t*)(mem) == variable;
252    }
253
254// =========== long
255
256    template <> inline uint32_t returnSize( const long& variable )
257    {
258        return sizeof(int32_t);
259    }
260
261    template <> inline void loadAndIncrease( const long& variable, uint8_t*& mem )
262    {
263        *(long*)( &variable ) = *(int32_t*)(mem);
264        mem += returnSize( variable );
265    }
266
267    template <> inline void saveAndIncrease( const long& variable, uint8_t*& mem )
268    {
269        *(int32_t*)(mem) = variable;
270        mem += returnSize( variable );
271    }
272
273    template <> inline bool checkEquality( const long& variable, uint8_t* mem )
274    {
275        return *(int32_t*)(mem) == variable;
276    }
277
278// =========== unsigned long
279
280    template <> inline uint32_t returnSize( const unsigned long& variable )
281    {
282        return sizeof(uint32_t);
283    }
284
285    template <> inline void loadAndIncrease( const unsigned long& variable, uint8_t*& mem )
286    {
287        *(unsigned long*)( &variable ) = *(uint32_t*)(mem);
288        mem += returnSize( variable );
289    }
290
291    template <> inline void saveAndIncrease( const unsigned long& variable, uint8_t*& mem )
292    {
293        *(uint32_t*)(mem) = variable;
294        mem += returnSize( variable );
295    }
296
297    template <> inline bool checkEquality( const unsigned long& variable, uint8_t* mem )
298    {
299        return *(uint32_t*)(mem) == variable;
300    }
301
302// =========== long long
303
304    template <> inline uint32_t returnSize( const long long& variable )
305    {
306        return sizeof(int64_t);
307    }
308
309    template <> inline void loadAndIncrease( const long long& variable, uint8_t*& mem )
310    {
311        *(long long*)( &variable ) = *(int64_t*)(mem);
312        mem += returnSize( variable );
313    }
314
315    template <> inline void saveAndIncrease( const long long& variable, uint8_t*& mem )
316    {
317        *(int64_t*)(mem) = variable;
318        mem += returnSize( variable );
319    }
320
321    template <> inline bool checkEquality( const long long& variable, uint8_t* mem )
322    {
323        return *(int64_t*)(mem) == variable;
324    }
325
326// =========== unsigned long long
327
328    template <> inline uint32_t returnSize( const unsigned long long& variable )
329    {
330        return sizeof(uint64_t);
331    }
332
333    template <> inline void loadAndIncrease( const unsigned long long& variable, uint8_t*& mem )
334    {
335        *(unsigned long long*)( &variable ) = *(uint64_t*)(mem);
336        mem += returnSize( variable );
337    }
338
339    template <> inline void saveAndIncrease( const unsigned long long& variable, uint8_t*& mem )
340    {
341        *(uint64_t*)(mem) = variable;
342        mem += returnSize( variable );
343    }
344
345    template <> inline bool checkEquality( const unsigned long long& variable, uint8_t* mem )
346    {
347        return *(uint64_t*)(mem) == variable;
348    }
349
350// =========== float
351
352    template <> inline uint32_t returnSize( const float& variable )
353    {
354        return sizeof(uint32_t);
355    }
356
357    template <> inline void loadAndIncrease( const float& variable, uint8_t*& mem )
358    {
359        *(uint32_t*)( &variable ) = *(uint32_t*)(mem);
360        mem += returnSize( variable );
361    }
362
363    template <> inline void saveAndIncrease( const float& variable, uint8_t*& mem )
364    {
365        *(uint32_t*)(mem) = *(uint32_t*)( &variable );
366        mem += returnSize( variable );
367    }
368
369    template <> inline bool checkEquality( const float& variable, uint8_t* mem )
370    {
371        return *(uint32_t*)(mem) == *(uint32_t*)( &variable );
372    }
373
374// =========== double
375
376    template <> inline uint32_t returnSize( const double& variable )
377    {
378        return sizeof(uint64_t);
379    }
380
381    template <> inline void loadAndIncrease( const double& variable, uint8_t*& mem )
382    {
383        *(uint64_t*)( &variable ) = *(uint64_t*)(mem);
384        mem += returnSize( variable );
385    }
386
387    template <> inline void saveAndIncrease( const double& variable, uint8_t*& mem )
388    {
389        *(uint64_t*)(mem) = *(uint64_t*)( &variable );
390        mem += returnSize( variable );
391    }
392
393    template <> inline bool checkEquality( const double& variable, uint8_t* mem )
394    {
395        return *(uint64_t*)(mem) == *(uint64_t*)( &variable );
396    }
397
398// =========== long double
399
400    template <> inline uint32_t returnSize( const long double& variable )
401    {
402        return sizeof(uint64_t);
403    }
404
405    template <> inline void loadAndIncrease( const long double& variable, uint8_t*& mem )
406    {
407        double temp;
408        memcpy(&temp, mem, sizeof(uint64_t));
409        *(long double*)( &variable ) = static_cast<long double>(temp);
410        mem += returnSize( variable );
411    }
412
413    template <> inline void saveAndIncrease( const long double& variable, uint8_t*& mem )
414    {
415        double temp = static_cast<double>(variable);
416        memcpy(mem, &temp, sizeof(uint64_t));
417        mem += returnSize( variable );
418    }
419
420    template <> inline bool checkEquality( const long double& variable, uint8_t* mem )
421    {
422        double temp = static_cast<double>(variable);
423        return memcmp(&temp, mem, sizeof(uint64_t))==0;
424    }
425       
426// =========== string
427
428    template <> inline uint32_t returnSize( const std::string& variable )
429    {
430        return variable.length()+1;
431    }
432
433    template <> inline void saveAndIncrease( const std::string& variable, uint8_t*& mem )
434    {
435        memcpy(mem, variable.c_str(), variable.length()+1);
436        mem += variable.length()+1;
437    }
438
439    template <> inline void loadAndIncrease( const std::string& variable, uint8_t*& mem )
440    {
441        *(std::string*)( &variable ) = (const char *)mem;
442        mem += variable.length()+1;
443    }
444
445    template <> inline bool checkEquality( const std::string& variable, uint8_t* mem )
446    {
447        //return std::string((const char*)mem)==variable;
448        return (const char*)mem==variable;
449    }
450
451// =========== Degree
452
453    template <> inline uint32_t returnSize( const Degree& variable )
454    {
455        return sizeof(Ogre::Real);
456    }
457
458    template <> inline void saveAndIncrease( const Degree& variable, uint8_t*& mem )
459    {
460        Ogre::Real r = variable.valueDegrees();
461        memcpy(mem, &r, returnSize( variable ));
462        mem += returnSize( variable );
463    }
464
465    template <> inline void loadAndIncrease( const Degree& variable, uint8_t*& mem )
466    {
467        Ogre::Real* r = (Ogre::Real*)mem;
468        (Degree&)variable = *r;
469        mem += returnSize( variable );
470    }
471
472     template <> inline bool checkEquality( const Degree& variable, uint8_t* mem )
473    {
474        Ogre::Real* r = (Ogre::Real*)mem;
475        return variable==Degree(*r);
476    }
477
478// =========== Radian
479
480    template <> inline uint32_t returnSize( const Radian& variable )
481    {
482        return sizeof(Ogre::Real);
483    }
484
485    template <> inline void saveAndIncrease( const Radian& variable, uint8_t*& mem )
486    {
487        Ogre::Real r = variable.valueRadians();
488        memcpy(mem, &r, returnSize( variable ));
489        mem += returnSize( variable );
490    }
491
492    template <> inline void loadAndIncrease( const Radian& variable, uint8_t*& mem )
493    {
494        Ogre::Real* r = (Ogre::Real*)mem;
495        (Radian&)variable = *r;
496        mem += returnSize( variable );
497    }
498
499    template <> inline bool checkEquality( const Radian& variable, uint8_t* mem )
500    {
501        Ogre::Real* r = (Ogre::Real*)mem;
502        return variable==Degree(*r);
503    }
504
505    // =========== Vector2
506
507    template <> inline uint32_t returnSize( const Vector2& variable )
508    {
509        return returnSize( variable.x )+returnSize( variable.y );
510    }
511
512    template <> inline void saveAndIncrease( const Vector2& variable, uint8_t*& mem )
513    {
514        saveAndIncrease( variable.x, mem );
515        saveAndIncrease( variable.y, mem );
516    }
517
518    template <> inline void loadAndIncrease( const Vector2& variable, uint8_t*& mem )
519    {
520        loadAndIncrease( variable.x, mem );
521        loadAndIncrease( variable.y, mem );
522    }
523
524    template <> inline bool checkEquality( const Vector2& variable, uint8_t* mem )
525    {
526        return checkEquality(variable.x, mem) && checkEquality(variable.y, mem+returnSize(variable.x));
527    }
528
529    // =========== Vector3
530
531    template <> inline uint32_t returnSize( const Vector3& variable )
532    {
533        return returnSize( variable.x )+returnSize( variable.y )+returnSize( variable.z );
534    }
535
536    template <> inline void saveAndIncrease( const Vector3& variable, uint8_t*& mem )
537    {
538        saveAndIncrease( variable.x, mem );
539        saveAndIncrease( variable.y, mem );
540        saveAndIncrease( variable.z, mem );
541    }
542
543    template <> inline void loadAndIncrease( const Vector3& variable, uint8_t*& mem )
544    {
545        loadAndIncrease( variable.x, mem );
546        loadAndIncrease( variable.y, mem );
547        loadAndIncrease( variable.z, mem );
548    }
549
550    template <> inline bool checkEquality( const Vector3& variable, uint8_t* mem )
551    {
552        return checkEquality(variable.x, mem) && checkEquality(variable.y, mem+returnSize(variable.x)) &&
553            checkEquality(variable.z, mem+returnSize(variable.x)+returnSize(variable.y));
554    }
555
556    // =========== Vector4
557
558    template <> inline uint32_t returnSize( const Vector4& variable )
559    {
560        return returnSize( variable.w )+returnSize( variable.x )+returnSize( variable.y )+returnSize( variable.z );
561    }
562
563    template <> inline void saveAndIncrease( const Vector4& variable, uint8_t*& mem )
564    {
565        saveAndIncrease( variable.w, mem );
566        saveAndIncrease( variable.x, mem );
567        saveAndIncrease( variable.y, mem );
568        saveAndIncrease( variable.z, mem );
569    }
570
571    template <> inline void loadAndIncrease( const Vector4& variable, uint8_t*& mem )
572    {
573        loadAndIncrease( variable.w, mem );
574        loadAndIncrease( variable.x, mem );
575        loadAndIncrease( variable.y, mem );
576        loadAndIncrease( variable.z, mem );
577    }
578
579    template <> inline bool checkEquality( const Vector4& variable, uint8_t* mem )
580    {
581        return checkEquality(variable.w, mem) && checkEquality(variable.x, mem+returnSize(variable.w)) &&
582            checkEquality(variable.y, mem+returnSize(variable.w)+returnSize(variable.x)) &&
583            checkEquality(variable.z, mem+returnSize(variable.w)+returnSize(variable.x)+returnSize(variable.y));
584    }
585
586    // =========== Quaternion
587
588    template <> inline uint32_t returnSize( const Quaternion& variable )
589    {
590        return returnSize( variable.w )+returnSize( variable.x )+returnSize( variable.y )+returnSize( variable.z );
591    }
592
593    template <> inline void saveAndIncrease( const Quaternion& variable, uint8_t*& mem )
594    {
595        saveAndIncrease( variable.w, mem );
596        saveAndIncrease( variable.x, mem );
597        saveAndIncrease( variable.y, mem );
598        saveAndIncrease( variable.z, mem );
599    }
600
601    template <> inline void loadAndIncrease( const Quaternion& variable, uint8_t*& mem )
602    {
603        loadAndIncrease( variable.w, mem );
604        loadAndIncrease( variable.x, mem );
605        loadAndIncrease( variable.y, mem );
606        loadAndIncrease( variable.z, mem );
607    }
608
609    template <> inline bool checkEquality( const Quaternion& variable, uint8_t* mem )
610    {
611        return checkEquality(variable.w, mem) && checkEquality(variable.x, mem+returnSize(variable.w)) &&
612            checkEquality(variable.y, mem+returnSize(variable.w)+returnSize(variable.x)) &&
613            checkEquality(variable.z, mem+returnSize(variable.w)+returnSize(variable.x)+returnSize(variable.y));
614    }
615
616    // =========== ColourValue
617
618    template <> inline uint32_t returnSize( const ColourValue& variable )
619    {
620        return returnSize( variable.r )+returnSize( variable.g )+returnSize( variable.b )+returnSize( variable.a );
621    }
622
623    template <> inline void saveAndIncrease( const ColourValue& variable, uint8_t*& mem )
624    {
625        saveAndIncrease( variable.r, mem );
626        saveAndIncrease( variable.g, mem );
627        saveAndIncrease( variable.b, mem );
628        saveAndIncrease( variable.a, mem );
629    }
630
631    template <> inline void loadAndIncrease( const ColourValue& variable, uint8_t*& mem )
632    {
633        loadAndIncrease( variable.r, mem );
634        loadAndIncrease( variable.g, mem );
635        loadAndIncrease( variable.b, mem );
636        loadAndIncrease( variable.a, mem );
637    }
638
639    template <> inline bool checkEquality( const ColourValue& variable, uint8_t* mem )
640    {
641        return checkEquality(variable.r, mem) && checkEquality(variable.g, mem+returnSize(variable.r)) &&
642            checkEquality(variable.b, mem+returnSize(variable.r)+returnSize(variable.g)) &&
643            checkEquality(variable.a, mem+returnSize(variable.r)+returnSize(variable.g)+returnSize(variable.b));
644    }
645
646    // =========== mbool
647
648    template <> inline uint32_t returnSize( const mbool& variable )
649    {
650        return returnSize( (unsigned char&)((mbool&)variable).getMemory() );
651    }
652
653    template <> inline void saveAndIncrease( const mbool& variable, uint8_t*& mem )
654    {
655        saveAndIncrease( (unsigned char&)((mbool&)variable).getMemory(), mem );
656    }
657
658    template <> inline void loadAndIncrease( const mbool& variable, uint8_t*& mem )
659    {
660        loadAndIncrease( (unsigned char&)((mbool&)variable).getMemory(), mem );
661    }
662
663    template <> inline bool checkEquality( const mbool& variable, uint8_t* mem )
664    {
665        return checkEquality( (unsigned char&)((mbool&)variable).getMemory(), mem );
666    }
667
668    // =========== std::set
669
670    template <class T> inline uint32_t returnSize( const std::set<T>& variable )
671    {
672        uint32_t tempsize = sizeof(uint32_t); // for the number of entries
673        for( typename std::set<T>::iterator it=((std::set<T>*)(&variable))->begin(); it!=((std::set<T>*)(&variable))->end(); ++it)
674            tempsize += returnSize( *it );
675        return tempsize;
676    }
677
678    template <class T> inline void saveAndIncrease(  const std::set<T>& variable, uint8_t*& mem )
679    {
680        typename std::set<T>::const_iterator it = variable.begin();
681        saveAndIncrease( (uint32_t)variable.size(), mem );
682        for( ; it!=variable.end(); ++it )
683            saveAndIncrease( *it, mem );
684    }
685
686    template <class T> inline void loadAndIncrease( const std::set<T>& variable, uint8_t*& mem )
687    {
688        uint32_t nrOfElements = 0;
689        loadAndIncrease( nrOfElements, mem );
690        typename std::set<T>::const_iterator it = variable.begin();
691        for( uint32_t i = 0; i<nrOfElements; ++i )
692        {
693            T temp;
694            loadAndIncrease(temp, mem);
695            while( it!=variable.end() && *it!=temp )
696            {
697                ((std::set<T>*)(&variable))->erase(it++);
698                ++it;
699            }
700            if( it==variable.end() )
701            {
702                ((std::set<T>*)(&variable))->insert(temp);
703            }
704        }
705    }
706
707    template <class T> inline bool checkEquality( const std::set<T>& variable, uint8_t* mem )
708    {
709        uint8_t* temp = mem;
710        uint32_t nrOfElements;
711        loadAndIncrease(nrOfElements, mem);
712        if( variable.size() == nrOfElements )
713        {
714            T tempT;
715            for( uint32_t i=0; i<nrOfElements; ++i )
716            {
717                loadAndIncrease(tempT, mem);
718                if( variable.find(tempT) == variable.end() )
719                {
720                    mem = temp;
721                    return false;
722                }
723            }
724        }
725        else
726        {
727            mem = temp;
728            return false;
729        }
730        return true;
731    }
732}
733
734
735#endif
Note: See TracBrowser for help on using the repository browser.