OSDN Git Service

* public snapshot of sid simulator
[pf3gnuchains/pf3gnuchains3x.git] / sid / include / sidattrutil.h
1 // sidattrutil.h - Classes to manage lists of component attributes and
2 // mappings between application objects and their string
3 // representations.  -*- C++ -*-
4
5 // Copyright (C) 1999, 2000 Red Hat.
6 // This file is part of SID and is licensed under the GPL.
7 // See the file COPYING.SID for conditions for redistribution.
8
9 #ifndef SIDATTRUTIL_H
10 #define SIDATTRUTIL_H
11
12 #include <sidconfig.h>
13 #include "sidtypes.h"
14
15 #include <string>
16 #include <typeinfo>
17 #include <map>
18
19 #include <cctype>
20 // XXX: kludge for compatibility both with old & new libstdc++
21 #if STD_CCTYPE
22 #define STDCTYPE(func) std::func
23 #else
24 #define STDCTYPE(func) func
25 #endif
26
27
28 #include <limits.h>
29
30
31 #ifdef HAVE_EXT_HASH_MAP
32 #include <ext/hash_map>
33 #define HAVE_HASHING 1
34 #else
35 #ifdef HAVE_HASH_MAP
36 #include <hash_map>
37 #define HAVE_HASHING 1
38 #else
39 #undef HAVE_HASHING
40 #endif
41 #endif
42
43 #if HAVE_SSTREAM
44 #include <sstream>
45 #elif HAVE_STRSTREAM_H
46 #include <strstream.h>
47 #else
48 #error "need <sstream> or <strstream.h>!"
49 #endif
50
51 #include <cassert>
52
53
54 namespace sidutil
55 {
56
57   // Make a string from an object by the default output-streaming operator.
58   template <typename Type>
59   static std::string
60   make_attribute (const Type& value)
61   {
62 #if HAVE_SSTREAM
63     std::ostringstream stream;
64     stream << value;
65     return stream.str ();
66 #elif HAVE_STRSTREAM_H
67     ostrstream stream;
68     stream << value;
69     std::string result (stream.str (), stream.pcount ());
70     stream.freeze (0);
71     return result;
72 #else
73 #error "need <sstream> or <strstream.h>!"
74 #endif
75   }
76
77
78   // Attempt to make object from a string using the default input-streaming operator.
79   template <typename Type>
80   static sid::component::status
81   parse_attribute (const std::string& str, Type& value)
82   {
83 #if HAVE_SSTREAM
84     std::istringstream stream (str);
85     stream >> value;
86 #elif HAVE_STRSTREAM_H
87     istrstream stream (str.data (), str.length ());
88     stream >> value;
89 #else
90 #error "need <sstream> or <strstream.h>!"
91 #endif
92
93     // Ensure stream is still good, and that operator>> has consumed entire string.
94     if (! stream.bad () && (stream.rdbuf ()->in_avail () == 0))
95       return sid::component::ok;
96     else
97       return sid::component::bad_value;
98   }
99
100
101
102 // ---------------------------------------------------------------------------
103
104   // Specific attribute make/parse routines for common types
105
106   // Specialization for strings
107 static std::string
108 make_attribute (const std::string& value)
109 {
110   return value;
111 }
112
113 static sid::component::status
114 parse_attribute (const std::string& str, std::string& value)
115 {
116   value = str;
117   return sid::component::ok;
118 }
119
120
121   // Specialization for bools
122 static std::string
123 make_attribute (const bool& value)
124 {
125   if (value)
126     return "yes";
127   else
128     return "no";
129 }
130
131 static sid::component::status
132 parse_attribute (const std::string& str, bool& value)
133 {
134   if (str == "yes" || str == "y" ||
135       str == "true" || str == "t" ||
136       str == "on" || 
137       str == "1")
138     {
139       value = true;
140       return sid::component::ok;
141     }
142   else if (str == "no" || str == "n" ||
143            str == "false" || str == "f" ||
144            str == "off" ||
145            str == "0")
146     {
147       value = false;
148       return sid::component::ok;
149     }
150
151   return sid::component::bad_value;
152 }
153
154
155   // Specialization for host_int_X
156
157 template <typename Value>
158 static std::string
159 make_numeric_attribute (const Value& value, std::ios::fmtflags ios_flags = std::ios::dec)
160 {
161 #if HAVE_SSTREAM
162     std::ostringstream stream;
163     stream.flags (ios_flags);
164     stream << value;
165     return stream.str ();
166 #elif HAVE_STRSTREAM_H
167     ostrstream stream;
168     stream.flags (ios_flags);
169     stream << value;
170     std::string result (stream.str (), stream.pcount ());
171     stream.freeze (0);
172     return result;
173 #else
174 #error "need <sstream> or <strstream.h>!"
175 #endif
176 }
177
178
179 static std::string
180 make_attribute (const sid::host_int_8& value)
181 {
182   return sidutil::make_numeric_attribute (value);
183 }
184
185 static std::string
186 make_attribute (const sid::host_int_4& value)
187 {
188   return sidutil::make_numeric_attribute (value);
189 }
190
191 static std::string
192 make_attribute (const sid::host_int_2& value)
193 {
194   return sidutil::make_numeric_attribute (value);
195 }
196
197 static std::string
198 make_attribute (const sid::host_int_1& value)
199 {
200   // widen to avoid representation as char
201   return sidutil::make_numeric_attribute (sid::host_int_2(value));
202 }
203
204 static std::string
205 make_attribute (const sid::signed_host_int_8& value)
206 {
207   return sidutil::make_numeric_attribute (value);
208 }
209
210 static std::string
211 make_attribute (const sid::signed_host_int_4& value)
212 {
213   return sidutil::make_numeric_attribute (value);
214 }
215
216 static std::string
217 make_attribute (const sid::signed_host_int_2& value)
218 {
219   return sidutil::make_numeric_attribute (value);
220 }
221
222 static std::string
223 make_attribute (const sid::signed_host_int_1& value)
224 {
225   // widen to avoid representation as char
226   return sidutil::make_numeric_attribute (sid::signed_host_int_2(value));
227 }
228
229
230 template <typename unsignedValue>
231 static sid::component::status
232 parse_unsigned_numeric_attribute (const std::string& str, unsignedValue& value)
233 {
234   // Algorithm based on newlib's strtoul, from BSD.
235
236   unsignedValue base = 10;
237   unsigned parseoffset = 0;
238   bool negative = false;
239
240   if (str.length () == 0)
241     return sid::component::bad_value;
242
243   if (str.length () > parseoffset+1 && str.substr (parseoffset,1) == "-")
244     {
245       negative = true;
246       parseoffset ++;
247     }
248
249   // NB: check longest prefixes first!
250   if (str.length () > parseoffset+2 && (str.substr (parseoffset,2) == "0x" || 
251                                         str.substr (parseoffset,2) == "0X"))
252     {
253       base = 16;
254       parseoffset += 2;
255     }
256   else if (str.length () > parseoffset+2 && (str.substr (parseoffset,2) == "0b" ||
257                                              str.substr (parseoffset,2) == "0B"))
258     {
259       base = 2;
260       parseoffset += 2;
261     }
262   else if (str.length () > parseoffset+1 && str.substr (parseoffset,1) == "0")
263     {
264       base = 8;
265       parseoffset += 1;
266     }
267
268   //cout << "str=" << str << " base=" << base << " negative=" << negative;
269
270   unsignedValue acc = 0;
271   unsignedValue max = (unsignedValue) -1;
272   unsignedValue cutoff = max / base;
273   unsignedValue cutlim = max % base;
274   for (unsigned i = parseoffset; i < str.length (); i++)
275     {
276       unsigned char c = str[i];
277       // cout << "c=" << (int)c << " acc=" << acc << endl;
278       if (STDCTYPE(isdigit) (c))
279         c -= '0';
280       else if (STDCTYPE(isalpha) (c))
281         c -= STDCTYPE(isupper) (c) ? 'A' - 10 : 'a' - 10;
282       else
283         return sid::component::bad_value;
284
285       // limit accumulation
286       if (c >= base)
287         return sid::component::bad_value;
288       else if (acc > cutoff || (acc == cutoff && c > cutlim))
289         return sid::component::bad_value;       
290
291       acc *= base;
292       acc += c;
293     }
294
295   value = negative ? -acc : acc;
296   // cout << " value=" << value << endl;
297
298   return sid::component::ok;
299 }
300
301
302 static sid::component::status
303 parse_attribute (const std::string& str, sid::host_int_8& value)
304 {
305   return sidutil::parse_unsigned_numeric_attribute (str, value);
306 }
307
308 static sid::component::status
309 parse_attribute (const std::string& str, sid::host_int_4& value)
310 {
311   return sidutil::parse_unsigned_numeric_attribute (str, value);
312 }
313
314 static sid::component::status
315 parse_attribute (const std::string& str, sid::host_int_2& value)
316 {
317   return sidutil::parse_unsigned_numeric_attribute (str, value);
318 }
319
320 static sid::component::status
321 parse_attribute (const std::string& str, sid::host_int_1& value)
322 {
323   return sidutil::parse_unsigned_numeric_attribute (str, value);
324 }
325
326 // Signed versions.
327 // ??? The unsigned versions don't mark negative values as bad so
328 // for now the signed versions don't mark big unsigned values as bad.
329
330 static sid::component::status
331 parse_attribute (const std::string& str, sid::signed_host_int_8& value)
332 {
333   sid::host_int_8 uvalue;
334   sid::component::status s = sidutil::parse_unsigned_numeric_attribute (str, uvalue);
335   if (s == sid::component::ok)
336     value = uvalue;
337   return s;
338 }
339
340 static sid::component::status
341 parse_attribute (const std::string& str, sid::signed_host_int_4& value)
342 {
343   sid::host_int_4 uvalue;
344   sid::component::status s = sidutil::parse_unsigned_numeric_attribute (str, uvalue);
345   if (s == sid::component::ok)
346     value = uvalue;
347   return s;
348 }
349
350 static sid::component::status
351 parse_attribute (const std::string& str, sid::signed_host_int_2& value)
352 {
353   sid::host_int_2 uvalue;
354   sid::component::status s = sidutil::parse_unsigned_numeric_attribute (str, uvalue);
355   if (s == sid::component::ok)
356     value = uvalue;
357   return s;
358 }
359
360 static sid::component::status
361 parse_attribute (const std::string& str, sid::signed_host_int_1& value)
362 {
363   sid::host_int_1 uvalue;
364   sid::component::status s = sidutil::parse_unsigned_numeric_attribute (str, uvalue);
365   if (s == sid::component::ok)
366     value = uvalue;
367   return s;
368 }
369
370
371
372 // Specialization for {big,little}_int types
373
374 template <typename IntType, bool IsBig>
375 static sid::component::status
376 parse_attribute (const std::string& str, sid::any_int<IntType,IsBig>& value)
377 {
378   typename sid::any_int<IntType,IsBig>::value_type v;
379   sid::component::status s = parse_attribute (str, v);
380   if (s == sid::component::ok)
381     value = v;
382   return s;
383 }
384
385 template <typename IntType, bool IsBig>
386 static std::string
387 make_attribute (const sid::any_int<IntType,IsBig>& value)
388 {
389   typename sid::any_int<IntType,IsBig>::value_type v = value.integer_value ();
390   return make_attribute (v);
391 }
392
393
394
395
396 // ---------------------------------------------------------------------------
397
398
399   // Abstract attribute-coder class provides interface to a pair of
400   // string->object and object->string conversion functions.
401   class attribute_coder_base
402   {
403   public:
404     virtual std::string make_attribute() const = 0;
405     virtual sid::component::status parse_attribute(const std::string& str) = 0;
406     virtual ~attribute_coder_base() {}
407   };
408
409
410   // This kind of attribute coder calls a pair of unparameterized
411   // member functions for making/parsing attribute strings.
412   template <class Class>
413   class attribute_coder_virtual: public attribute_coder_base
414   {
415   public:
416     typedef std::string (Class::*getter_f) ();
417     typedef sid::component::status (Class::*setter_f) (const std::string&);    
418
419   private:
420     Class* receiver;
421     getter_f getter;
422     setter_f setter;
423
424   public:
425     attribute_coder_virtual (Class* r, getter_f g, setter_f s):
426       receiver (r), getter (g), setter (s) {}
427
428     attribute_coder_virtual (Class* r, setter_f s, getter_f g):
429       receiver (r), getter (g), setter (s) {}
430
431     std::string make_attribute () const
432       { return (receiver->*getter) (); }
433
434     sid::component::status
435     parse_attribute (const std::string& str)
436       { return (receiver->*setter) (str); }
437
438     ~attribute_coder_virtual() { }
439   };
440
441
442   // This kind of attribute coder redirects the calls to another
443   // object's named attribute.  This may be used to create
444   // aliased attributes.
445   class attribute_coder_alias: public attribute_coder_base
446   {
447   private:
448     sid::component* receiver;
449     std::string name;
450
451   public:
452     attribute_coder_alias (sid::component* r, const std::string& n):
453       receiver (r), name(n) {}
454
455     std::string make_attribute () const
456       { return receiver->attribute_value (name); }
457
458     sid::component::status
459     parse_attribute (const std::string& str)
460       { return receiver->set_attribute_value (name, str); }
461
462     ~attribute_coder_alias() { }
463   };
464
465
466
467   // This kind of attribute coder calls a pair of member functions for 
468   // making/parsing attribute strings.  They are parameterized with a
469   // value of some type.
470   template <class Class, typename Parameter>
471   class attribute_coder_virtual_parameterized: public attribute_coder_base
472   {
473   public:
474     typedef std::string (Class::*getter_f) (Parameter);
475     typedef sid::component::status (Class::*setter_f)
476       (Parameter, const std::string&);    
477
478   private:
479     Class* receiver;
480     Parameter parameter;
481     getter_f getter;
482     setter_f setter;
483
484   public:
485     attribute_coder_virtual_parameterized (Class* r, getter_f g, setter_f s,
486                                          Parameter p)
487       :receiver (r), getter (g), setter (s), parameter (p) { }
488       
489     attribute_coder_virtual_parameterized (Class* r, setter_f s, getter_f g,
490                                          Parameter p)
491       :receiver (r), getter (g), setter (s), parameter (p) { }
492       
493     std::string
494     make_attribute () const
495       {
496         return (receiver->*getter) (parameter);
497       }
498
499     sid::component::status
500     parse_attribute (const std::string& str)
501       {
502         return (receiver->*setter) (parameter, str);
503       }
504
505    ~attribute_coder_virtual_parameterized() { }
506
507   };
508
509
510   // This attribute coder stores a pointer to a value.  It forwards
511   // make_attribute and parse_attribute to the pointed-to value for
512   // mapping to/from strings.
513   template <typename Value>
514   class attribute_coder: public attribute_coder_base
515   {
516     Value* ptr;
517   public:
518     attribute_coder (Value* p): ptr (p) {}
519
520     std::string make_attribute () const
521       {
522         return sidutil::make_attribute (*ptr);
523       }
524
525     sid::component::status parse_attribute (const std::string& str)
526       {
527         return sidutil::parse_attribute (str, *ptr);
528       }
529
530     ~attribute_coder() { }
531   };
532
533
534   // This attribute coder stores a pointer to a value.  It forwards
535   // make_attribute to the pointed-to value for mapping from
536   // strings. It intercepts parse_attribute to prevent a value change.
537   template <typename Value>
538   class attribute_coder_ro: public attribute_coder<Value>
539   {
540   public:
541     attribute_coder_ro (Value* p): attribute_coder<Value> (p) {}
542
543     // Override to disable writing.
544     sid::component::status
545     parse_attribute (const std::string& str)
546       {
547         return sid::component::bad_value;
548       }
549     
550     ~attribute_coder_ro() { }
551   };
552
553
554   // This attribute coder stores a literal const value.  It forwards
555   // make_attribute to the value for mapping from strings.  It
556   // intercepts parse_attribute to prevent a value change.
557   template <typename Value>
558   class attribute_coder_ro_value: public attribute_coder_base
559   {
560     const Value value;
561
562   public:
563     attribute_coder_ro_value (const Value& v): value (v) {}
564
565     std::string make_attribute () const
566       {
567         return sidutil::make_attribute (value);
568       }
569
570     sid::component::status parse_attribute (const std::string& str)
571       {
572         return sid::component::bad_value; 
573       }
574     
575     ~attribute_coder_ro_value() { }
576  
577   };
578
579
580   // This attribute coder is like basic attribute_coder<>, but it
581   // calls a notification function after any parse_attribute attempt.
582   template <typename Value, class Class>
583   class attribute_coder_notify: public attribute_coder<Value>
584   {
585     typedef void (Class::*Callback) ();
586     Class* receiver;
587     Callback pmf;
588
589   public:
590     attribute_coder_notify (Value* p, Class* rec, Callback f):
591       attribute_coder<Value> (p), receiver (rec), pmf (f) {}
592
593     sid::component::status
594     parse_attribute (const std::string& str)
595       {
596         sid::component::status stat = 
597           attribute_coder<Value>::parse_attribute (str);
598         // XXX: make sense to call pmf if stat != ok?
599         // XXX: could even endavour to restore previous value if != ok
600          (receiver->*pmf) ();
601         return stat;
602       }
603   };
604
605
606   // This attribute coder class performs its work by reading/writing
607   // a fixed address via a bus.
608   template <class DataType>
609   class attribute_coder_bus_rw: public attribute_coder_base
610   {
611     mutable sid::bus* target;
612     sid::host_int_4 address;
613
614   public:
615     attribute_coder_bus_rw (sid::bus* t, sid::host_int_4 a)
616                           : target (t), address (a) 
617       {
618         assert (t != 0);
619       }
620
621     std::string make_attribute () const
622       { 
623         DataType value;
624         sid::bus::status s2 = this->target->read (address, value);
625         if (s2 == sid::bus::ok) return sidutil::make_attribute (value);
626         else return "";
627       }
628
629     sid::component::status parse_attribute (const std::string& str)
630       {
631         DataType value;
632         sid::component::status s1 = sidutil::parse_attribute (str, value);
633         if (s1 != sid::component::ok) return s1;
634         sid::bus::status s2 = this->target->write (address, value);
635         if (s2 == sid::bus::ok) return sid::component::ok;
636         else return sid::component::bad_value;
637       }
638     
639     ~attribute_coder_bus_rw() { }
640   };
641
642
643   // This is a read-only variety of the same thing.
644   template <class DataType>
645   class attribute_coder_bus_ro: public attribute_coder_bus_rw<DataType>
646   {
647   public:
648     attribute_coder_bus_ro (sid::bus* t, sid::host_int_4 a): 
649       attribute_coder_bus_rw<DataType> (t, a) {}
650
651     sid::component::status parse_attribute (const std::string& str)
652       {
653         return sid::component::bad_value;
654       }
655   };
656
657
658   // This is a write-only variety of the same thing.  It returns the
659   // last successfully written value on reads.
660   template <class DataType>
661   class attribute_coder_bus_wo: public attribute_coder_bus_rw<DataType>
662   {
663   public:
664     attribute_coder_bus_wo (sid::bus* t, sid::host_int_4 a): 
665       attribute_coder_bus_rw<DataType> (t, a),
666       last_written_attribute ("no value")
667       {}
668
669     std::string make_attribute () const
670       { 
671         return this->last_written_attribute;
672       }
673
674     sid::component::status parse_attribute (const std::string& str)
675       {
676         sid::component::status s = attribute_coder_bus_rw<DataType>::parse_attribute (str);
677         if (s == sid::component::ok)
678           this->last_written_attribute = str;
679         return s;
680       }
681
682    ~attribute_coder_bus_wo() { }
683
684   private:
685     std::string last_written_attribute;
686   };
687
688
689 #ifdef HAVE_HASHING
690   struct hash_string
691   {
692     size_t
693     operator () (const std::string& s) const
694       {
695         // XXX: improve? 
696         return std::hash<const char*> () (s.c_str ()); 
697       }
698   };
699 #endif
700
701
702   // A mix-in for classes with largely static attribute lists.
703   class fixed_attribute_map_component: public virtual sid::component
704   {
705   private:
706     // use hash table for this, if available
707 #ifdef HAVE_HASHING
708     typedef std::hash_map<std::string,attribute_coder_base*,hash_string> attribute_map_t;
709 #else
710     typedef std::map<std::string,attribute_coder_base*> attribute_map_t;
711 #endif
712     mutable attribute_map_t attribute_map;
713
714   private:
715     // map attribute name <-> category name
716
717     // Each matching entry in these parallel lists represents one
718     // attribute name <-> category name relationship.
719     std::vector<std::string> category_pair_attribute;
720     std::vector<std::string> category_pair_category;
721
722     // XXX: This used to be a pair of string->set<string> maps, but
723     // the compiler working set blew up.
724     
725   protected:
726     ~fixed_attribute_map_component () { /* XXX: delete coder objects */ }
727
728     // Add or remove an attribute <-> category association.  The named
729     // attribute must already exist.
730     void
731     categorize (const std::string& attr, const std::string& category)
732       {
733         assert (this->attribute_map.find (attr) != this->attribute_map.end ());
734
735         // Add a matching pair into the category_pair vectors.
736         this->category_pair_attribute.push_back (attr);
737         this->category_pair_category.push_back (category);
738
739         // size of both vectors should be same 
740         assert (this->category_pair_attribute.size () == 
741                                         this->category_pair_category.size ());
742       }
743
744
745     // Remove all entry pairs from the category_pair vectors where the
746     // attribute name matches the argument attr.
747     void
748     uncategorize (const std::string& attr)
749       {
750         assert (this->attribute_map.find (attr) != this->attribute_map.end ());
751
752         // Remove all entry pairs from the category_pair vectors where
753         // the attribute name matches.
754         unsigned i = 0;
755
756         while (i < this->category_pair_attribute.size ())
757           {
758             if (this->category_pair_attribute[i] == attr)
759               {
760                 this->category_pair_attribute.erase (
761                                 this->category_pair_attribute.begin () + i);
762
763                 this->category_pair_category.erase (
764                                 this->category_pair_category.begin () + i );
765               }
766             else
767               i++;
768           }
769         
770         assert (this->category_pair_attribute.size () == 
771                 this->category_pair_category.size ());
772       }
773
774
775     // Low level add-attribute: supply associated coder instance
776     // XXX: candidates for moving out-of-line
777     void
778     add_attribute_coder (const std::string& name,
779                         attribute_coder_base* coder_ptr)
780       {
781         assert (this->attribute_map.find (name) == this->attribute_map.end ());
782         this->attribute_map[name] = coder_ptr;
783       }
784     
785     
786     void
787     add_attribute_coder (const std::string& name,
788                         attribute_coder_base* coder_ptr, 
789                         const std::string& category)
790       {
791         this->add_attribute_coder (name, coder_ptr);
792         this->categorize (name, category);
793       }
794
795     // Add basic attribute; use streaming conversions
796     template <typename Value>
797     void
798     add_attribute (const std::string& name, Value* ptr)
799       { 
800         this->add_attribute_coder (name, new attribute_coder<Value> (ptr)); 
801       }
802
803     
804     template <typename Value>
805     void
806     add_attribute (const std::string& name, Value* ptr, 
807                   const std::string& category)
808       { 
809         this->add_attribute (name, ptr);
810         this->categorize (name, category);
811       }
812     
813     // Add read-only attribute
814     template <typename Value>
815     void
816     add_attribute_ro (const std::string& name, Value* str_ptr)
817       {
818         this->add_attribute_coder (name,
819                                   new attribute_coder_ro<Value> (str_ptr));
820       }
821     
822     template <typename Value>
823     void
824     add_attribute_ro (const std::string& name, Value* str_ptr, 
825                      const std::string& category)
826       {
827         this->add_attribute_ro (name, str_ptr);
828         this->categorize (name, category);
829       }
830     
831     
832     // Add read-only value attribute
833     template <typename Value>
834     void
835     add_attribute_ro_value (const std::string& name, const Value& v)
836       {
837         this->add_attribute_coder (name,
838                                   new attribute_coder_ro_value<Value> (v));
839       }
840     
841     
842     template <typename Value>
843     void
844     add_attribute_ro_value (const std::string& name, const Value& v,
845                            const std::string& category)
846       {
847         this->add_attribute_ro_value (name, v);
848         this->categorize (name, category);
849       }
850
851     // Add an attribute alias
852     void
853     add_attribute_alias (const std::string& aka, const std::string& name)
854       {
855         this->add_attribute_coder (aka,
856                                    new attribute_coder_alias (this, name));
857       }
858
859     void
860     add_attribute_alias (const std::string& aka, const std::string& name, 
861                          const std::string& category)
862       {
863         this->add_attribute_alias (aka, name);
864         this->categorize (name, category);
865       }
866
867     
868     // Add a r/w attribute.  After a write, call given function.
869     template <typename Value, class Class>
870     void
871     add_attribute_notify (const std::string& name, Value* str_ptr, 
872                          Class* receiver,
873                          void (Class::*pmf) ())
874       {
875         this->add_attribute_coder (name, 
876                                   new attribute_coder_notify<Value,Class>
877                                   (str_ptr, receiver, pmf));
878       }
879     
880     template <typename Value, class Class>
881     void
882     add_attribute_notify (const std::string& name, Value* str_ptr, 
883                          Class* receiver,
884                          void (Class::*pmf) (),
885                          const std::string& category)
886       {
887         this->add_attribute_notify (name, str_ptr, receiver, pmf);
888         this->categorize (name, category);
889       }
890     
891     
892     // Add a r/w attribute.  Use given functions for getting/setting values.
893     template <class Class, typename Getter, typename Setter>
894     void
895     add_attribute_virtual (const std::string& name,
896                           Class* receiver,
897                           Getter getter,
898                           Setter setter)
899       {
900         this->add_attribute_coder (name,
901                                   new attribute_coder_virtual<Class> (receiver,
902                                                                       getter, 
903                                                                       setter));
904       }
905     
906     template <class Class, typename Getter, typename Setter>
907     void
908     add_attribute_virtual (const std::string& name,
909                           Class* receiver,
910                           Getter getter,
911                           Setter setter,
912                           const std::string& category)
913       {
914         this->add_attribute_virtual (name, receiver, getter, setter);
915         this->categorize (name, category);
916       }
917
918     // Add a parameterized r/w attribute.  Use given functions for getting/setting values.
919     template <class Class, typename Getter, typename Setter, typename Parameter>
920     void
921     add_attribute_virtual_parameterized (const std::string& name,
922                                          Parameter param,
923                                          Class* receiver,
924                                          Getter getter,
925                                          Setter setter)
926       {
927         this->add_attribute_coder (name,
928                                    new attribute_coder_virtual_parameterized<Class,Parameter>
929                                    (receiver,
930                                     getter, 
931                                     setter,
932                                     param));
933       }
934
935
936     template <class Class, typename Getter, typename Setter, typename Parameter>
937     void
938     add_attribute_virtual_parameterized (const std::string& name,
939                                          Parameter param,
940                                          Class* receiver,
941                                          Getter getter,
942                                          Setter setter,
943                                          const std::string& category)
944       {
945         this->add_attribute_virtual_parameterized (name,
946                                                    param,
947                                                    receiver,
948                                                    getter, 
949                                                    setter);
950         this->categorize (name, category);
951       }
952
953
954
955     // Removes attribute name from component.
956     void
957     remove_attribute (const std::string& name)
958       {
959         assert (this->attribute_map.find (name) != this->attribute_map.end ());
960         this->uncategorize (name);
961         this->attribute_map.erase (name);
962         // XXX: delete coder?
963       }
964     
965     
966   public:
967     // Returns vector containing names of all component's attributes.  
968     std::vector<std::string>
969     attribute_names () throw()
970       {
971         std::vector<std::string> names;
972         for (attribute_map_t::const_iterator it = 
973                                this->attribute_map.begin();
974              it != this->attribute_map.end();
975              it++)
976            {
977              names.push_back ((*it).first);
978            }
979         return names;
980       }
981     
982     // Method returns the names of a component's attribute in a given
983     // category.
984     std::vector<std::string>
985     attribute_names (const std::string& category) throw()
986       {
987          std::vector<std::string> attrs;
988          for (unsigned i= 0; i< this->category_pair_category.size(); i++)
989             {
990               if (this->category_pair_category[i] == category)
991                 attrs.push_back (this->category_pair_attribute[i]);
992             }
993          return attrs;
994       }
995     
996     // Method returns attribute value corresponding to attribute name
997     // passed as argument. Method returns value in std::string form
998     // using make_atribute method.
999     std::string
1000     attribute_value (const std::string& name) throw()
1001       {
1002         attribute_map_t::iterator it = this->attribute_map.find(name);
1003         if (it == this->attribute_map.end())
1004           return "";
1005         else
1006           return ((*it).second)->make_attribute ();
1007       }
1008     
1009     
1010     // Method sets attribute value corresponding to attribute name (arg. 1).
1011     // The value of attribute is set by parsing argument value using
1012     // parse_attribute method. Method returns ok if value is set.
1013     component::status
1014     set_attribute_value (const std::string& name,
1015                         const std::string& value) throw()
1016       {
1017             attribute_map_t::iterator it = this->attribute_map.find (name);
1018             if (it == this->attribute_map.end ())
1019               return component::not_found;
1020             else
1021               return ((*it).second)->parse_attribute (value);
1022       }
1023   };
1024 }
1025
1026 #endif // SIDATTRUTIL_H