00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00047 #ifndef PLATFORMSTL_INCL_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP
00048 #define PLATFORMSTL_INCL_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP
00049
00050
00051 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00052 # define PLATFORMSTL_VER_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP_MAJOR 2
00053 # define PLATFORMSTL_VER_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP_MINOR 3
00054 # define PLATFORMSTL_VER_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP_REVISION 1
00055 # define PLATFORMSTL_VER_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP_EDIT 56
00056 #endif
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #ifndef PLATFORMSTL_INCL_PLATFORMSTL_HPP_PLATFORMSTL
00073 # include <platformstl/platformstl.hpp>
00074 #endif
00075 #ifndef PLATFORMSTL_INCL_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_VARIABLE_TRAITS
00076 # include <platformstl/system/environment_variable_traits.hpp>
00077 #endif
00078
00079 #if defined(PLATFORMSTL_OS_IS_UNIX)
00080
00081 #elif defined(PLATFORMSTL_OS_IS_WINDOWS)
00082
00083 #else
00084 # error Operating system not discriminated
00085 #endif
00086
00087 #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_LIBRARY_DISCRIMINATOR
00088 # include <stlsoft/util/std/library_discriminator.hpp>
00089 #endif
00090 #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE
00091 # include <stlsoft/smartptr/scoped_handle.hpp>
00092 #endif
00093 #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SHARED_PTR
00094 # include <stlsoft/smartptr/shared_ptr.hpp>
00095 #endif
00096 #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
00097 # include <stlsoft/shims/access/string.hpp>
00098 #endif
00099 #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS
00100 # include <stlsoft/string/split_functions.hpp>
00101 #endif
00102 #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
00103 # include <stlsoft/util/std/iterator_helper.hpp>
00104 #endif
00105 #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
00106 # include <stlsoft/collections/util/collections.hpp>
00107 #endif
00108
00109 #ifndef STLSOFT_INCL_MAP
00110 # define STLSOFT_INCL_MAP
00111 # include <map>
00112 #endif
00113 #ifndef STLSOFT_INCL_UTILITY
00114 # define STLSOFT_INCL_UTILITY
00115 # include <utility>
00116 #endif
00117
00118
00119
00120
00121
00122 #if defined(_STLSOFT_NO_NAMESPACE) || \
00123 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00124
00125 namespace platformstl
00126 {
00127 #else
00128
00129
00130 namespace stlsoft
00131 {
00132
00133 namespace platformstl_project
00134 {
00135 #endif
00136
00137
00138
00139
00140
00148 class environment_map
00149 : public stlsoft_ns_qual(stl_collection_tag)
00150 {
00153 private:
00154 typedef environment_variable_traits traits_type;
00155 typedef stlsoft_ns_qual_std(string) string_type;
00156 public:
00160 typedef string_type first_type;
00164 typedef string_type second_type;
00166 typedef std::pair< const first_type
00167 , second_type
00168 > value_type;
00170 typedef ss_size_t size_type;
00172 typedef ss_ptrdiff_t difference_type;
00174 typedef const value_type const_reference;
00176 class const_iterator;
00177 #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \
00178 !defined(STLSOFT_COMPILER_IS_BORLAND)
00179 typedef const_reverse_bidirectional_iterator_base< const_iterator
00180 , value_type
00181 , const_reference
00182 , void
00183 , difference_type
00184 > const_reverse_iterator;
00185 #endif
00187 typedef environment_map class_type;
00188
00189 private:
00190 friend class const_iterator;
00191 class snapshot
00192 {
00193 public:
00194 typedef stlsoft_ns_qual(shared_ptr)<snapshot> ref_type;
00195 #if defined(STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC) && \
00196 STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION == STLSOFT_CF_DINKUMWARE_VC_VERSION_7_0
00197
00198 typedef stlsoft_ns_qual_std(map)< first_type
00199 #else
00200 typedef stlsoft_ns_qual_std(map)< const first_type
00201 #endif
00202 , second_type
00203 > variables_type_;
00204 typedef variables_type_::iterator iterator;
00205
00206 public:
00207 snapshot();
00208
00209 public:
00210 ss_bool_t erase( first_type const& name) throw();
00211 void erase( iterator it) throw();
00212 void insert( first_type const &name
00213 , second_type const& value);
00214 void set( first_type const& name
00215 , second_type const& value);
00216 ss_bool_t lookup( first_type const& name
00217 , second_type*& pvalue) throw();
00218
00219 public:
00220 iterator begin();
00221 iterator end();
00222
00223 private:
00224 variables_type_ m_variables;
00225 };
00227
00230 public:
00236 environment_map();
00238
00241 public:
00249 second_type operator [](char const* name) const;
00257 second_type operator [](first_type const& name) const;
00258
00263 ss_bool_t lookup(char const* name, second_type& value) const;
00268 ss_bool_t lookup(first_type const& name, second_type& value) const;
00270
00273 public:
00280 void refresh();
00282
00285 public:
00286 #ifdef PLATFORMSTL_ENVVAR_SET_SUPPORTED
00294 void insert(first_type const& name, second_type const& value);
00295
00300 void insert(char const* name, char const* value);
00301 #endif
00302 #ifdef PLATFORMSTL_ENVVAR_ERASE_SUPPORTED
00306 size_type erase(first_type const& name);
00307
00311 size_type erase(char const* name);
00312
00314 void erase(const_iterator it);
00315 #endif
00317
00320 public:
00321 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00325 const_iterator begin() const;
00329 const_iterator end() const;
00330 # if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \
00331 !defined(STLSOFT_COMPILER_IS_BORLAND)
00335 const_reverse_iterator rbegin() const;
00339 const_reverse_iterator rend() const;
00340 # endif
00341 #endif
00343
00346 public:
00347 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00354 class const_iterator
00355 : public stlsoft_ns_qual(iterator_base)<stlsoft_ns_qual_std(bidirectional_iterator_tag)
00356 , value_type
00357 , ss_ptrdiff_t
00358 , void
00359 , const value_type
00360 >
00361 {
00364 public:
00365 typedef const_iterator class_type;
00367
00370 private:
00371 friend class environment_map;
00372 const_iterator(snapshot::iterator it, snapshot::ref_type snapshot);
00373 public:
00374 const_iterator();
00375 const_iterator(class_type const& rhs);
00377
00380 public:
00381 class_type& operator ++();
00382 class_type operator ++(int);
00383 const_reference operator *() const;
00385
00388 public:
00389 class_type& operator --();
00390 class_type operator --(int);
00392
00395 public:
00396 ss_bool_t equal(class_type const& rhs) const;
00398
00401 private:
00402 snapshot::iterator m_it;
00403 snapshot::ref_type m_snapshot;
00405 };
00406 #endif
00408
00411 private:
00412 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00413 void check_refresh_snapshot_() const;
00414 #endif
00416
00419 private:
00420 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00421 mutable snapshot::ref_type m_snapshot;
00422 #endif
00424
00427 private:
00428 environment_map(environment_map const& rhs);
00429 environment_map& operator =(environment_map const& rhs);
00431 };
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 #if ( defined(STLSOFT_COMPILER_IS_BORLAND) && \
00442 __BORLANDC__ >= 0x0560) || \
00443 defined(STLSOFT_COMPILER_IS_DMC)
00444
00445 # if defined(_STLSOFT_NO_NAMESPACE) || \
00446 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00447 }
00448 # else
00449 }
00450 }
00451 # endif
00452
00453 #endif
00454
00455 inline stlsoft_ns_qual(ss_bool_t) operator ==( platformstl_ns_qual(environment_map)::const_iterator const& lhs
00456 , platformstl_ns_qual(environment_map)::const_iterator const& rhs)
00457 {
00458 return lhs.equal(rhs);
00459 }
00460 inline stlsoft_ns_qual(ss_bool_t) operator !=( platformstl_ns_qual(environment_map)::const_iterator const& lhs
00461 , platformstl_ns_qual(environment_map)::const_iterator const& rhs)
00462 {
00463 return !lhs.equal(rhs);
00464 }
00465
00466
00467 #if ( defined(STLSOFT_COMPILER_IS_BORLAND) && \
00468 __BORLANDC__ >= 0x0560) || \
00469 defined(STLSOFT_COMPILER_IS_DMC)
00470
00471 # if defined(_STLSOFT_NO_NAMESPACE) || \
00472 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00473
00474 namespace platformstl
00475 {
00476 # else
00477
00478
00479 namespace stlsoft
00480 {
00481
00482 namespace platformstl_project
00483 {
00484 # endif
00485
00486 #endif
00487
00489
00490
00491 #ifdef STLSOFT_UNITTEST
00492 # include "./unittest/environment_map_unittest_.h"
00493 #endif
00494
00495
00496
00497
00498
00499 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00500
00501
00502
00503 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00504 inline environment_map::const_iterator::const_iterator()
00505 : m_it()
00506 {}
00507
00508 inline environment_map::const_iterator::const_iterator(environment_map::snapshot::iterator it, environment_map::snapshot::ref_type snapshot)
00509 : m_it(it)
00510 , m_snapshot(snapshot)
00511 {}
00512
00513 inline environment_map::const_iterator::const_iterator(environment_map::const_iterator::class_type const& rhs)
00514 : m_it(rhs.m_it)
00515 , m_snapshot(rhs.m_snapshot)
00516 {}
00517
00518 inline environment_map::const_iterator::class_type& environment_map::const_iterator::operator ++()
00519 {
00520 ++m_it;
00521
00522 return *this;
00523 }
00524
00525 inline environment_map::const_iterator::class_type environment_map::const_iterator::operator ++(int)
00526 {
00527 class_type r(*this);
00528
00529 operator ++();
00530
00531 return r;
00532 }
00533
00534 inline environment_map::const_reference environment_map::const_iterator::operator *() const
00535 {
00536 return *m_it;
00537 }
00538
00539 inline environment_map::const_iterator::class_type& environment_map::const_iterator::operator --()
00540 {
00541 --m_it;
00542
00543 return *this;
00544 }
00545
00546 inline environment_map::const_iterator::class_type environment_map::const_iterator::operator --(int)
00547 {
00548 class_type r(*this);
00549
00550 operator --();
00551
00552 return r;
00553 }
00554
00555 inline ss_bool_t environment_map::const_iterator::equal(environment_map::const_iterator::class_type const& rhs) const
00556 {
00557 return m_it == rhs.m_it;
00558 }
00559 #endif
00560
00561
00562
00563 inline environment_map::environment_map()
00564 {}
00565
00566 inline environment_map::second_type environment_map::operator [](char const* name) const
00567 {
00568 char const *value = traits_type::get_variable(name);
00569
00570 if(NULL == value)
00571 {
00572 STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("variable does not exist"));
00573 }
00574
00575 return value;
00576 }
00577
00578 inline environment_map::second_type environment_map::operator [](environment_map::first_type const& name) const
00579 {
00580 return operator [](name.c_str());
00581 }
00582
00583 inline ss_bool_t environment_map::lookup(char const* name, environment_map::second_type& value) const
00584 {
00585 char const *value_ = traits_type::get_variable(name);
00586
00587 return (NULL == value_) ? false : (value = value_, true);
00588 }
00589
00590 inline ss_bool_t environment_map::lookup(environment_map::first_type const& name, environment_map::second_type& value) const
00591 {
00592 return lookup(name.c_str(), value);
00593 }
00594
00595 inline void environment_map::refresh()
00596 {
00597 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00598 m_snapshot.close();
00599 #endif
00600 }
00601
00602 #ifdef PLATFORMSTL_ENVVAR_SET_SUPPORTED
00603 inline void environment_map::insert(environment_map::first_type const& name, environment_map::second_type const& value)
00604 {
00605
00606 STLSOFT_MESSAGE_ASSERT("Name may not be empty", !name.empty());
00607 STLSOFT_MESSAGE_ASSERT("Name may not contain '='", name.end() == std::find(name.begin(), name.end(), '='));
00608 STLSOFT_MESSAGE_ASSERT("Empty value not allowed in insertion", !value.empty());
00609
00610 second_type *pstr = NULL;
00611
00612 if( 1 < m_snapshot.use_count() &&
00613 m_snapshot->lookup(name, pstr))
00614 {
00615
00616
00617
00618
00619
00620 pstr->reserve(value.size());
00621
00622
00623 if(0 != traits_type::set_variable(name.c_str(), value.c_str()))
00624 {
00625 STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot set environment variable"));
00626 }
00627
00628
00629 m_snapshot->set(name, value);
00630 }
00631 else
00632 {
00633
00634
00635
00636 if(1 < m_snapshot.use_count())
00637 {
00638 m_snapshot->insert(name, value);
00639 }
00640
00641 if(0 != traits_type::set_variable(name.c_str(), value.c_str()))
00642 {
00643 if(1 < m_snapshot.use_count())
00644 {
00645 m_snapshot->erase(name);
00646 }
00647
00648 STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot set environment variable"));
00649 }
00650 }
00651 }
00652
00653 inline void environment_map::insert(char const* name, char const* value)
00654 {
00655
00656 STLSOFT_ASSERT(NULL != name);
00657 STLSOFT_MESSAGE_ASSERT("Name may not be empty", 0 != ::strlen(name));
00658 STLSOFT_MESSAGE_ASSERT("Name may not contain '='", NULL == ::strchr(name, '='));
00659 STLSOFT_MESSAGE_ASSERT("Null value not allowed in insertion", NULL != value);
00660 STLSOFT_MESSAGE_ASSERT("Empty value not allowed in insertion", 0 != ::strlen(value));
00661
00662 insert(first_type(name), second_type(value));
00663 }
00664 #endif
00665
00666 #ifdef PLATFORMSTL_ENVVAR_ERASE_SUPPORTED
00667 inline environment_map::size_type environment_map::erase(environment_map::first_type const& name)
00668 {
00669
00670 STLSOFT_MESSAGE_ASSERT("Name may not be empty", !name.empty());
00671 STLSOFT_MESSAGE_ASSERT("Name may not contain '='", name.end() == std::find(name.begin(), name.end(), '='));
00672
00673 size_type b = 0;
00674
00675 if(0 != traits_type::erase_variable(name.c_str()))
00676 {
00677 #if 0
00678
00679
00680
00681
00682
00683
00684
00685 if(NULL != traits_type::get_variable(name.c_str()))
00686 #endif
00687 {
00688 STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot erase environment variable"));
00689 }
00690 }
00691 else
00692 {
00693 b = 1;
00694 }
00695
00696 if(1 < m_snapshot.use_count())
00697 {
00698 if(m_snapshot->erase(name))
00699 {
00700 b = 1;
00701 }
00702 }
00703
00704 return b;
00705 }
00706
00707 inline environment_map::size_type environment_map::erase(char const* name)
00708 {
00709
00710 STLSOFT_ASSERT(NULL != name);
00711 STLSOFT_MESSAGE_ASSERT("Name may not be empty", 0 != ::strlen(name));
00712 STLSOFT_MESSAGE_ASSERT("Name may not contain '='", NULL == ::strchr(name, '='));
00713
00714 return erase(first_type(name));
00715 }
00716
00717 inline void environment_map::erase(environment_map::const_iterator it)
00718 {
00719 STLSOFT_MESSAGE_ASSERT("No snapshot assigned, so erase() is inappropriate; maybe premature call to clear()", 1 < m_snapshot.use_count());
00720
00721 #if 0
00722 first_type const &name = (*it).first;
00723 #else
00724 first_type const &name = (*it.m_it).first;
00725 #endif
00726
00727 if(0 != traits_type::erase_variable(name.c_str()))
00728 {
00729 #if 0
00730
00731
00732
00733
00734
00735
00736
00737 if(NULL != traits_type::get_variable(name.c_str()))
00738 #endif
00739 {
00740 STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot erase environment variable"));
00741 }
00742 }
00743
00744 m_snapshot->erase(it.m_it);
00745 }
00746 #endif
00747
00748 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00749 inline environment_map::const_iterator environment_map::begin() const
00750 {
00751 check_refresh_snapshot_();
00752
00753 #if 0
00754 snapshot::ref_type snapshot = m_snapshot;
00755
00756 return const_iterator(snapshot->begin(), m_snapshot);
00757 #else
00758 return const_iterator(m_snapshot->begin(), m_snapshot);
00759 #endif
00760 }
00761
00762 inline environment_map::const_iterator environment_map::end() const
00763 {
00764 check_refresh_snapshot_();
00765
00766 #if 0
00767 snapshot::ref_type snapshot = m_snapshot;
00768
00769 return const_iterator(snapshot->end(), m_snapshot);
00770 #else
00771 return const_iterator(m_snapshot->end(), m_snapshot);
00772 #endif
00773 }
00774
00775 # if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \
00776 !defined(STLSOFT_COMPILER_IS_BORLAND)
00777 inline environment_map::const_reverse_iterator environment_map::rbegin() const
00778 {
00779 return const_reverse_iterator(end());
00780 }
00781
00782 inline environment_map::const_reverse_iterator environment_map::rend() const
00783 {
00784 return const_reverse_iterator(begin());
00785 }
00786 # endif
00787 #endif
00788
00789 #ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00790 inline void environment_map::check_refresh_snapshot_() const
00791 {
00792 if(m_snapshot.use_count() < 2)
00793 {
00794 m_snapshot = snapshot::ref_type(new snapshot());
00795 }
00796 }
00797 #endif
00798
00799
00800
00801 # ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
00802
00803 inline environment_map::snapshot::snapshot()
00804 {
00805 first_type name;
00806 second_type value;
00807
00808 stlsoft::scoped_handle<char const**> env( traits_type::get_environ()
00809 , &traits_type::release_environ);
00810
00811 { for(char const** p = env.get(); NULL != *p; ++p)
00812 {
00813 stlsoft::split(*p, '=', name, value);
00814
00815 m_variables[name] = value;
00816 }}
00817 }
00818
00819 inline environment_map::snapshot::iterator environment_map::snapshot::begin()
00820 {
00821 return m_variables.begin();
00822 }
00823
00824 inline environment_map::snapshot::iterator environment_map::snapshot::end()
00825 {
00826 return m_variables.end();
00827 }
00828
00829 inline ss_bool_t environment_map::snapshot::erase(first_type const& name) throw()
00830 {
00831 variables_type_::iterator it = m_variables.find(name);
00832
00833 if(m_variables.end() != it)
00834 {
00835 m_variables.erase(it);
00836
00837 return true;
00838 }
00839
00840 return false;
00841 }
00842
00843 inline void environment_map::snapshot::erase(environment_map::snapshot::iterator it) throw()
00844 {
00845 m_variables.erase(it);
00846 }
00847
00848 inline void environment_map::snapshot::insert(first_type const& name, second_type const& value)
00849 {
00850 # if 0
00852 m_variables[name] = value;
00853 # else
00855 m_variables.insert(value_type(name, value));
00856 # endif
00857 }
00858
00859 inline void environment_map::snapshot::set(first_type const& name, second_type const& value)
00860 {
00861 variables_type_::iterator it = m_variables.find(name);
00862
00863 STLSOFT_ASSERT(m_variables.end() != it);
00864 STLSOFT_ASSERT((*it).second.capacity() >= value.size());
00865
00866 # ifdef _DEBUG
00867 try
00868 # endif
00869 {
00870 (*it).second.assign(value);
00871 }
00872 # ifdef _DEBUG
00873 catch(...)
00874 {
00875 STLSOFT_MESSAGE_ASSERT("Should never happen", 0);
00876
00877 throw;
00878 }
00879 # endif
00880
00881 }
00882
00883 inline ss_bool_t environment_map::snapshot::lookup(first_type const& name, second_type *&pvalue) throw()
00884 {
00885 variables_type_::iterator it = m_variables.find(name);
00886
00887 if(m_variables.end() == it)
00888 {
00889 return false;
00890 }
00891 else
00892 {
00893 pvalue = &(*it).second;
00894
00895 return true;
00896 }
00897 }
00898
00899 # endif
00900
00901 #endif
00902
00903
00904
00905 #if defined(_STLSOFT_NO_NAMESPACE) || \
00906 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00907 }
00908 #else
00909 }
00910 }
00911 #endif
00912
00913
00914
00915 #endif
00916
00917