root/OpenSceneGraph/trunk/applications/osgversion/Contributors.cpp @ 10638

Revision 10638, 21.7 kB (checked in by robert, 5 years ago)

Updated ChangeLog?, wrappers and Contributors lists

Line 
1// The majority of the application is dedicated to building the
2// current contribitors list by parsing the ChangeLog, it just takes
3// one line in the main itself to report the version number.
4
5#include <set>
6#include <vector>
7#include <iostream>
8
9#include <OpenThreads/Version>
10
11#include <osg/Notify>
12#include <osg/Version>
13#include <osg/ArgumentParser>
14#include <osg/ApplicationUsage>
15
16#include <osg/Matrix>
17#include <osg/Plane>
18#include <osg/BoundingBox>
19#include <osg/BoundingSphere>
20
21#include <osgDB/fstream>
22
23using namespace std;
24
25
26#if defined(_MSC_VER)
27    #pragma setlocale("C")
28#endif
29
30typedef pair<string, string>        NamePair;
31typedef map<NamePair, unsigned int> NameMap;
32typedef vector<string>              Words;
33
34NamePair EmptyNamePair;
35NamePair NameRobertOsfield("Robert", "Osfield");
36NamePair NameDonBurns     ("Don",    "Burns");
37
38
39const char* validNames[] =
40{
41    "de",
42    "den",
43    "van"
44};
45
46const char* invalidNames[] =
47{
48    "Added",
49    "AnimationPath",
50    "AnimationPathCallback",
51    "AnimationPathManipulator",
52    "ArgumentParser",
53    "AttrData",
54    "AutoTransform",
55    "AutoTransform.",
56    "Azimuth",
57    "BlenColour(Vec4",
58    "Camera",
59    "CameraBarrierCallback",
60    "CameraNode",
61    "Canvas",
62    "CluserCullingCallback",
63    "ClusterCullingCallback",
64    "CoordinateSystem",
65    "CoordinateSystemNode",
66    "CoordinateSystemNode&",
67    "CopyOp",
68    "Copyright",
69    "Core",
70    "Creator",
71    "CullCallbacks",
72    "CullingSettngs",
73    "CullVisitor",
74    "CullVistor",
75    "Cygwin",
76    "DatabasePager",
77    "DataSet",
78    "DataVariance",
79    "DeleteHandler",
80    "DisplaySettings",
81    "Drawable",
82    "DrawElementsUByte",
83    "Endian",
84    "Escape",
85    "EventQueue",
86    "Face",
87    "Files",
88    "Fixed",
89    "Fixes",
90    "FluidProgram",
91    "FontImplementation",
92    "FrameStats",
93    "Framstamp",
94    "FreeBSD",
95    "Geode",
96    "GeoemtryTechnique",
97    "GeometryTechnique",
98    "GeoSet",
99    "GraphicsContext",
100    "GraphicsContextImplementation",
101    "GraphicsThread",
102    "GraphicsWindowX11",
103    "Group",
104    "Image",
105    "ImageOptions",
106    "Images",
107    "Images/SolarSystem",
108    "ImageStream",
109    "Improved",
110    "IndexBlock",
111    "IndexFaceSets",
112    "IntersectVisitor",
113    "Inventor",
114    "KdTree",
115    "KeyboardMouse",
116    "KeyboardMouseCallback",
117    "LightModel",
118    "LightPointNode",
119    "LineSegment",
120    "LineStipple",
121    "Logos",
122    "LongIDRecord",
123    "Make",
124    "Makefile",
125    "Material",
126    "Matrix",
127    "Matrix*",
128    "MatrixManipulator",
129    "MatrixTransform",
130    "MemoryManager",
131    "MergeGeometryVisitor",
132    "MeshRecord",
133    "Mode",
134    "Mr",
135    "Multigen",
136    "New",
137    "NewCullVisitor",
138    "NodeVisitor",
139    "Object",
140    "OpenDX",
141    "OpenSceneGraph",
142    "OpenSceneGraph-2",
143    "OpenSceneGraph-osgWidget-dev",
144    "OpenThreads",
145    "OperationThread",
146    "Optimizer",
147    "OrientationConverter",
148    "Osfields",
149    "Ouput",
150    "Output",
151    "OveralyNode",
152    "PagedLOD",
153    "PageLOD",
154    "Paging",
155    "ParentList",
156    "Performer",
157    "PickHandler",
158    "PixelDataBufferObject",
159    "PolygonStipple",
160    "PolytopeVisitor",
161    "PrimitiveIndexFunctor",
162    "Prodcuer",
163    "Producer",
164    "ProducerEventCallback",
165    "Program",
166    "Proxy",
167    "ProxyNode",
168    "Quake3",
169    "Quicktime",
170    "ReaderWriters",
171    "ReentrantMutex",
172    "Referenced",
173    "ReferenceFrame",
174    "Removed",
175    "RemoveLoadedProxyNodes",
176    "RenderStage",
177    "RenderTargetFallback",
178    "RenderToTextureStage",
179    "SceneGraphBuilder",
180    "SceneView",
181    "Sequence",
182    "Shape",
183    "SimpleViewer",
184    "SimpleViewer",
185    "SmokeTrailEffect",
186    "Source",
187    "SpotExponent",
188    "State",
189    "StateAttribute",
190    "Stats",
191    "StatsVisitor",
192    "Studio",
193    "Support",
194    "Switch",
195    "TechniqueEventHandler",
196    "TerraPage",
197    "TessellationHints",
198    "TestManipulator",
199    "TestSupportCallback",
200    "TexEnv",
201    "TexMat(Matrix",
202    "Texture",
203    "Texture2DArray",
204    "Texture3D",
205    "TextureCubeMap",
206    "TextureObjectManager",
207    "TextureRectangle",
208    "TextureRectangle(Image*",
209    "TextureType",
210    "Texuture",
211    "TriStripVisitor",
212    "TrPageViewer",
213    "Uniform",
214    "UseFarLineSegments",
215    "UserData",
216    "Valve",
217    "Vec*",
218    "Vec2d",
219    "Vec3d",
220    "Vec4ub",
221    "Version",
222    "VertexData",
223    "View",
224    "Viewer",
225    "ViewPoint",
226    "Viewport",
227    "Viewport",
228    "Visual",
229    "VisualStudio",
230    "WindowData",
231    "Windows",
232    "X",
233    "Xcode",
234    "GraphicsWindowWin32",
235    "ImageLayer",
236    "Xml",
237    "Y"
238};
239
240
241struct TypoCorrection
242{
243    const char* original;
244    const char* corrected;
245};
246
247TypoCorrection typoCorrections[] =
248{
249    {"Aderian",        "Adrian"},
250    {"Adndre",         "Andre"},
251    {"Adrain",         "Adrian"},
252    {"Amueller",       "Aumueller"},
253    {"Andew",          "Andrew"},
254    {"André",         "André"},
255    {"Antione",        "Antoine"},
256    {"Antonoine",      "Antoine"},
257    {"Atr",            "Art"},
258    {"Baverage",       "Beverage"},
259    {"Bistroviae",     "Bistrovic"},
260    {"Callue",         "Callu"},
261    {"Christaiansen""Christiansen"},
262    {"Cobin",          "Corbin"},
263    {"Comporesi",      "Camporesi"},
264    {"Connel",         "Connell"},
265    {"Cullu",          "Callu"},
266    {"Daneil",         "Daniel"},
267    {"Daust",          "Daoust"},
268    {"Daved",          "David"},
269    {"Drederic",       "Frederic"},
270    {"Eileman",        "Eilemann"},
271    {"Elgi",           "Egli"},
272    {"Fabian",         "Fabien"},
273    {"Fautre",         "Fautré"},
274    {"Frashid",        "Farshid"},
275    {"Fred",           "Frederic"},
276    {"Fredrick",       "Frederic"},
277    {"Fredric",        "Frederic"},
278    {"Froechlich",     "Fröhlich"},
279    {"Froehilch",      "Fröhlich"},
280    {"Froehlich",      "Fröhlich"},
281    {"Froelich",       "Fröhlich"},
282    {"Froenlich",      "Fröhlich"},
283    {"Fröhlich",      "Fröhlich"},
284    {"Fruciel",        "Frauciel"},
285    {"García",        "Garcea"},
286    {"Garrat",         "Garrett"},
287    {"Garret",         "Garrett"},
288    {"Geof",           "Geoff"},
289    {"Giatan",         "Gaitan"},
290    {"Gronenger",      "Gronager"},
291    {"Gronger",        "Gronager"},
292    {"Haritchablaet""Haritchabalet"},
293    {"Hebelin",        "Herbelin"},
294    {"Heirtlein",      "Hertlein"},
295    {"Heirtlein",      "Hertlein"},
296    {"Hertleinm",      "Hertlein"},
297    {"Happalahti",     "Haapalahti"},
298    {"Hertlien",       "Hertlein"},
299    {"Hi",             "He"},
300    {"Hooper",         "Hopper"},
301    {"Inverson",       "Iverson"},
302    {"Iversion",       "Iverson"},
303    {"Jean-Sebastein", "Jean-Sebastien"},
304    {"Jean-Sebastian", "Jean-Sebastien"},
305    {"Jean-Sebastirn", "Jean-Sebastien"},
306    {"Jea-Sebastien""Jean-Sebastien"},
307    {"Johhansen",      "Johansen"},
308    {"Johnansen",      "Johansen"},
309    {"Johnasen",       "Johansen"},
310    {"Jolly",          "Jolley"},
311    {"Jose",           "José"},
312    {"José",          "José"},
313    {"Joson",          "Jason"},
314    {"J",              "José"},
315    {"Keuhne",         "Kuehne"},
316    {"Kheune",         "Kuehne"},
317    {"Lagrade",        "Lagarde"},
318    {"Largade",        "Lagarde"},
319    {"Larshkari",      "Lashkari"},
320    {"Lashakari",      "Lashkari"},
321    {"Lashari",        "Lashkari"},
322    {"Lasharki",       "Lashkari"},
323    {"Laskari",        "Lashkari"},
324    {"Leandowski",     "Lewandowski"},
325    {"Lawandowski",    "Lewandowski"},
326    {"Luacas",         "Luaces"},
327    {"Luacas",         "Luaces"},
328    {"Liech",          "Leich"},
329    {"Lugi",           "Luigi"},
330    {"Lweandowski",    "Lewandowski"},
331    {"Maceij",         "Maciej"},
332    {"Machler",        "Mächler"},
333    {"Macro",          "Marco"},
334    {"Maechler",       "Mächler"},
335    {"Mahai",          "Mihai"},
336    {"Mammond",        "Marmond"},
337    {"March",          "Marco"},
338    {"Martsz",         "Martz"},
339    {"Marz",           "Martz"},
340    {"Matz",           "Martz"},
341    {"Melchoir",       "Melchior"},
342    {"Mellis",         "Melis"},
343    {"Messerschimdt""Messerschmidt"},
344    {"Micheal",        "Michael"},
345    {"Mihair",         "Mihai"},
346    {"Molishtan",      "Moloshtan"},
347    {"Molishtan",      "Moloshtan"},
348    {"Moloshton",      "Moloshtan"},
349    {"Morné",         "Morné"},
350    {"Morne",          "Morné"},
351    {"Moule",          "Moiule"},
352    {"Narache",        "Marache"},
353    {"Nicklov",        "Nikolov"},
354    {"Nickolov",       "Nikolov"},
355    {"Olad",           "Olaf"},
356    {"Olar",           "Olaf"},
357    {"Oritz",          "Ortiz"},
358    {"Osfeld",         "Osfield"},
359    {"Osfied",         "Osfield"},
360    {"Pail",           "Paul"},
361    {"Rajce",          "Trajce"},
362    {"Randal",         "Randall"},
363    {"Robet",          "Robert"},
364    {"Rodger",         "Roger"},
365    {"Rolad",          "Roland"},
366    {"Riddel",         "Riddell"},
367    {"Rucard",         "Richard"},
368    {"Sekender",       "Sukender"},
369    {"Sewel",          "Sewell"},
370    {"Simmonson",      "Simonsson"},
371    {"Simmonsson",     "Simonsson"},
372    {"Sjolie",         "Sjölie"},
373    {"Sjölie",        "Sjölie"},
374    {"Skinnder",       "Skinner"},
375    {"Sokolosky",      "Sokolowsky"},
376    {"Sokolowky",      "Sokolowsky"},
377    {"Sokolowki",      "Sokolowsky"},
378    {"Sokolowski",     "Sokolowsky"},
379    {"Sokolsky",       "Sokolowsky"},
380    {"Sokolwsky",      "Sokolowsky"},
381    {"Sonda",          "Sondra"},
382    {"Stansilav",      "Stanislav"},
383    {"Stefan",         "Stephan"},
384    {"Stell",          "Steel"},
385    {"Sylvan",         "Sylvain"},
386    {"Takeahei",       "Takahei"},
387    {"Takehei",        "Takahei"},
388    {"Tery",           "Terry"},
389    {"Tarantilils",    "Tarantilis"},
390    {"Trastenjak",     "Trstenjak"},
391    {"Urlich",         "Ulrich"},
392    {"Vines",          "Vine"},
393    {"Waldrom",        "Waldron"},
394    {"Wedner",         "Weidner"},
395    {"Weidemann",      "Wiedemann"},
396    {"Wieblen",        "Weiblen"},
397    {"Woesnner",       "Woessner"},
398    {"Wojchiech",      "Wojciech"},
399    {"Wojiech",        "Wojciech"},
400    {"Xennon",         "Hanson"},
401    {"Yefrei",         "Yefei"},
402    {"Yfei",           "Yefei"}
403};
404
405
406struct NameCorrection
407{
408    const char* originalFirst;
409    const char* originalSecond;
410    const char* correctedFirst;
411    const char* correctedSecond;
412};
413
414NameCorrection nameCorrections[] =
415{
416    {"Cesar",          "L.B.",
417     "César",          "L. B. Silveira"},
418    {"Marc",           "Sciabica",
419     "Mark",           "Sciabica"},
420    {"Jean",           "Sebastien",
421     "Jean-Sebastien", "Guay"},
422    {"Michale",        "Platings",
423     "Michael",        "Platings"},
424    {"Mick",           "",
425     "Maik",           "Keller"},
426    {"Gary",           "Quin",
427     "Gary",           "Quinn"},
428    {"BjornHein",      "",
429     "Björn",          "Hein"},
430    {"Bjorn",          "Hein",
431     "Björn",          "Hein"},
432    {"Erik",           "van",
433     "Erik",           "den Dekker"},
434    {"Erik",           "den",
435     "Erik",           "den Dekker"},
436    {"Jeoen",          "den",
437     "Jeroen",         "den Dekker"},
438    {"John",           "Vidar",
439     "John",           "Vidar Larring"},
440    {"John",           "Vida",
441     "John",           "Vidar Larring"},
442    {"Sebastien",      "Messerschmidt",
443     "Sebastian",      "Messerschmidt"},
444    {"Mattias",        "Fröhlich",
445     "Mathias",        "Fröhlich"},
446    {"Mathias",        "Helsing",
447     "Mattias",        "Helsing"},
448    {"Jose",           "Delport",
449     "J.P.",           "Delport"},
450    {"José",           "Delport",
451     "J.P.",           "Delport"},
452    {"Franz",          "Melchior",
453     "Melchior",       "Franz"},
454    {"Glen",           "Waldon",
455     "Glenn",          "Waldron"},
456    {"Ralf",           "Karn",
457     "Ralf",           "Kern"},
458    {"Donny",          "Cipperly",
459     "Donald",         "Cipperly"},
460    {"Gino",           "van",
461     "Gino",           "van den Bergen"},
462    {"Radu",           "Mihai",
463     "Mihai",          "Radu"},
464    {"Art",            "Trevs",
465     "Art",            "Tevs"},
466    {"Tim",            "More",
467     "Tim",            "Moore"},
468    {"Andre",          "Garneau",
469     "André",          "Garneau"},
470    {"Eric",           "Hammil",
471     "Chris",          "Hanson"},
472    {"Paul",           "de",
473     "Paul",           "de Repentigny"},
474    {"Raymond",        "de",
475     "Raymond",        "de Vries"},
476    {"Nick",           "",
477     "Trajce",         "Nikolov"},
478    {"Daniel",         "",
479     "Daniel",         "Sjölie"},
480    {"Julia",          "Ortiz",
481     "Julian",         "Ortiz"},
482    {"Rune",           "Schmidt",
483     "Rune",           "Schmidt Jensen"},
484    {"Romano",         "José",
485     "Romano",         "José Magacho da Silva"},
486    {"Rommano",        "Silva",
487     "Romano",         "José Magacho da Silva"},
488    {"Leandro",        "Motta",
489     "Leandro",        "Motta Barros"},
490    {"A",              "Botorabi",
491     "Ali",            "Botorabi"},
492    {"Waltice",        "",
493     "Walter",         "J. Altice"},
494    {"Drew",           "",
495     "Drew",           "Whitehouse"},
496    {"Douglas",        "A",
497     "Douglas",        "A. Pouk"},
498    {"Colin",          "MacDonald",
499     "Colin",          "McDonald"},
500    {"Nikolov",        "Trajce",
501     "Trajce",         "Nikolov"},
502    {"Frauciel",       "Luc",
503     "Luc",            "Frauciel"},
504    {"Alberto",        "Lucas",
505     "Alberto",        "Luaces"},
506};
507
508
509bool validName(const string& first)
510{
511    // Check for valid names
512    for (unsigned int i = 0; i < sizeof(validNames) / sizeof(char*); ++i)
513    {
514        if (first == validNames[i])
515        {
516            return true;
517        }
518    }
519
520    if (first.empty()) return false;
521
522    if (first[0] < 'A' || first[0] > 'Z') return false;
523
524    if (first.size() >= 2 && (first[1] < 'a' || first[1] > 'z') && (first[1] != '.') && (first[1] != ',')) return false;
525
526    // Check for invalid names
527    for (unsigned int i = 0; i < sizeof(invalidNames) / sizeof(char*); ++i)
528    {
529        if (first == invalidNames[i])
530        {
531            return false;
532        }
533    }
534
535    // Default to a valid name
536    return true;
537}
538
539
540string typoCorrection(const string& name)
541{
542    // Loop over all known typo corrections
543    for (unsigned int i = 0; i < sizeof(typoCorrections) / sizeof(TypoCorrection); ++i)
544    {
545        // If a typo is found
546        if (name == typoCorrections[i].original)
547        {
548            // Return the correction
549            return typoCorrections[i].corrected;
550        }
551    }
552
553    return name;
554}
555
556
557void nameCorrection(NamePair& name)
558{
559    // Loop over all known name corrections
560    for (unsigned int i = 0; i < sizeof(nameCorrections) / sizeof(NameCorrection); ++i)
561    {
562        // If a matching name is found
563        if (name.first  == nameCorrections[i].originalFirst &&
564            name.second == nameCorrections[i].originalSecond)
565        {
566            // Return the correction
567            name.first  = nameCorrections[i].correctedFirst;
568            name.second = nameCorrections[i].correctedSecond;
569
570            // Early out, since we don't want corrections of corrections
571            return;
572        }
573    }
574}
575
576
577void lastValidCharacter(const string& name, unsigned int& pos, char c)
578{
579    for (unsigned int i = 0; i < pos; ++i)
580    {
581        if (name[i] == c)
582        {
583            pos = i;
584            return;
585        }
586    }
587}
588
589
590void lastValidCharacter(const string& name, unsigned int& last)
591{
592    lastValidCharacter(name, last, '.');
593    lastValidCharacter(name, last, ',');
594    lastValidCharacter(name, last, '\'');
595    lastValidCharacter(name, last, '/');
596    lastValidCharacter(name, last, '\\');
597    lastValidCharacter(name, last, ':');
598    lastValidCharacter(name, last, ';');
599    lastValidCharacter(name, last, ')');
600}
601
602
603NamePair createName(const string& first, const string& second)
604{
605    if (first.empty()) return EmptyNamePair;
606
607//  cout << "first = " << first << " second = " << second << endl;
608
609    unsigned int last = first.size();
610    lastValidCharacter(first, last);
611
612    if (last == 0) return EmptyNamePair;
613
614    string name;
615
616    name.append(first.begin(), first.begin() + last);
617
618    if (!validName(name)) return EmptyNamePair;
619
620    name = typoCorrection(name);
621
622    if (second.empty() ||
623        !validName(second))
624    {
625        // filter any single or two letter words as unlike to be names.
626        if (name.size() <= 2) return EmptyNamePair;
627
628        return NamePair(name, "");
629    }
630
631    last = second.size();
632
633    lastValidCharacter(second, last);
634
635    if (last > 0)
636    {
637        string surname(second.begin(), second.begin() + last);
638
639        if (validName(surname))
640        {
641            surname = typoCorrection(surname);
642            return NamePair(name, surname);
643        }
644    }
645
646    // filter any single or two letter words as unlike to be names.
647    if (name.size() <= 2) return EmptyNamePair;
648
649    return NamePair(name, "");
650}
651
652
653bool submissionsSequence(const Words& words, unsigned int& i)
654{
655    if (i + 1 >= words.size()) return false;
656
657    if (words[i] == "From"   ||
658        words[i] == "from"   ||
659        words[i] == "From:"  ||
660        words[i] == "from:"  ||
661        words[i] == "Merged" ||
662        words[i] == "Integrated") return true;
663
664    if (i + 2 >= words.size()) return false;
665
666    if (words[i] == "submitted" && words[i + 1] == "by")
667    {
668        i += 1;
669        return true;
670    }
671
672    if (words[i] == "Folded" && words[i + 1] == "in")
673    {
674        i += 1;
675        return true;
676    }
677
678    if (words[i] == "Rolled" && words[i + 1] == "in")
679    {
680        i += 1;
681        return true;
682    }
683
684    if (words[i] == "Checked" && words[i + 1] == "in")
685    {
686        i += 1;
687        return true;
688    }
689
690    if (i + 3 >= words.size()) return false;
691
692    if (words[i] == "sent" && words[i + 1] == "in" && words[i + 2] == "by")
693    {
694        i += 2;
695        return true;
696    }
697
698    return false;
699}
700
701
702void readContributors(NameMap& names, const string& file)
703{
704    osgDB::ifstream fin(file.c_str());
705
706    Words words;
707    while(fin)
708    {
709        string keyword;
710        fin >> keyword;
711        words.push_back(keyword);
712    }
713
714    string blank_string;
715
716    for(unsigned int i = 0; i < words.size(); ++i)
717    {
718        if (submissionsSequence(words, i))
719        {
720            if (i + 2 < words.size() && validName(words[i + 1]))
721            {
722                NamePair name = createName(words[i + 1], words[i + 2]);
723                nameCorrection(name);
724                if (!name.first.empty()) ++names[name];
725                i += 2;
726            }
727            else if (i + 1 < words.size() && validName(words[i + 1]))
728            {
729                NamePair name = createName(words[i + 1], blank_string);
730                nameCorrection(name);
731                if (!name.first.empty()) ++names[name];
732                i += 1;
733            }
734        }
735        else
736        {
737            if (words[i] == "robert")
738            {
739                ++names[NameRobertOsfield];
740            }
741            else if (words[i] == "don")
742            {
743                ++names[NameDonBurns];
744            }
745        }
746    }
747
748    // reassign fisrt name entries to their full names entries
749    if (names.size() > 1)
750    {
751        for (NameMap::iterator itr = names.begin(); itr != names.end(); )
752        {
753            if (itr->first.second.empty())
754            {
755                NameMap::iterator next_itr = itr;
756                ++next_itr;
757
758                if (next_itr != names.end() && itr->first.first == next_itr->first.first)
759                {
760                    next_itr->second += itr->second;
761                    names.erase(itr);
762                    itr = next_itr;
763                }
764                else
765                {
766                    ++itr;
767                }
768            }
769            else
770            {
771                ++itr;
772            }
773        }
774    }
775
776    // remove the double entries from Robert's contributions
777    if (names.size() > 1)
778    {
779        for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr)
780        {
781            if (itr->first != NameRobertOsfield && itr->first != NameDonBurns)
782            {
783                names[NameRobertOsfield] -= itr->second;
784            }
785        }
786    }
787}
788
789
790void buildContributors(NameMap& names)
791{
792    // top five contributors
793    ++names[NamePair("Robert",     "Osfield")];
794    ++names[NamePair("Don",        "Burns")];
795    ++names[NamePair("Marco",      "Jez")];
796    ++names[NamePair("Mike",       "Weiblen")];
797    ++names[NamePair("Geoff",      "Michel")];
798    ++names[NamePair("Ben",        "van Basten")];
799
800    // contributors that don't appear in the ChangeLog due to their contributions
801    // being before CVS started for the OSG, or before the name logging began.
802    ++names[NamePair("Karsten",    "Weiss")];
803    ++names[NamePair("Graeme",     "Harkness")];
804    ++names[NamePair("Axel",       "Volley")];
805    ++names[NamePair("Nikolaus",   "Hanekamp")];
806    ++names[NamePair("Kristopher", "Bixler")];
807    ++names[NamePair("Tanguy",     "Fautré")];
808    ++names[NamePair("J.E.",       "Hoffmann")];
809}
810
811
812void printContributors(const std::string& changeLog, bool printNumEntries)
813{
814    NameMap names;
815    buildContributors(names);
816    if (!changeLog.empty())
817    {
818        readContributors(names, changeLog);
819    }
820
821    typedef multimap<unsigned int, NamePair> SortedNameMap;
822
823    SortedNameMap sortedNames;
824    for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr)
825    {
826        sortedNames.insert(SortedNameMap::value_type(itr->second, itr->first));
827    }
828
829    cout << names.size() << " Contributors:" << endl << endl;
830
831    if (printNumEntries)
832    {
833        cout << "Entries Firstname Surname" << endl;
834        cout << "-------------------------" << endl;
835        for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr)
836        {
837            cout << sitr->first << "\t" << sitr->second.first << " " << sitr->second.second << endl;
838        }
839    }
840    else
841    {
842        cout << "Firstname Surname" << endl;
843        cout << "-----------------" << endl;
844        for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr)
845        {
846            cout << sitr->second.first << " " << sitr->second.second << endl;
847        }
848    }
849}
Note: See TracBrowser for help on using the browser.