diff options
Diffstat (limited to 'dep/acelite/ace/Lib_Find.cpp')
-rw-r--r-- | dep/acelite/ace/Lib_Find.cpp | 768 |
1 files changed, 768 insertions, 0 deletions
diff --git a/dep/acelite/ace/Lib_Find.cpp b/dep/acelite/ace/Lib_Find.cpp new file mode 100644 index 00000000000..b1a2f6a4160 --- /dev/null +++ b/dep/acelite/ace/Lib_Find.cpp @@ -0,0 +1,768 @@ +// $Id: Lib_Find.cpp 85473 2009-06-01 08:09:31Z johnnyw $ + +#include "ace/Lib_Find.h" +#include "ace/Log_Msg.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_errno.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_unistd.h" +#include "ace/OS_NS_stdlib.h" +#include "ace/OS_Memory.h" +#include "ace/OS_NS_fcntl.h" + +#if defined (ACE_WIN32) +# include "ace/OS_NS_strings.h" +#endif /* ACE_WIN32 */ + +#if defined (ACE_OPENVMS) +#include "ace/RB_Tree.h" +#include "ace/Thread_Mutex.h" +#include "ace/Singleton.h" + +#include /**/ "descrip.h" +#include /**/ "chfdef.h" +#include /**/ "stsdef.h" +#include /**/ "libdef.h" + +extern "C" int LIB$FIND_IMAGE_SYMBOL(...); + +/** + * @internal + * + * Implements a class to register symbols and addresses for use with DLL + * symbol retrieval. + * + * OpenVMS restricts symbol length to 31 characters encoding any symbols + * longer than that. In these cases dlsym() only works with the encoded + * names. + * This creates serious problems for the service configurator framework + * where the factory method names often exceed 31 chars and where loading + * is based on retrieval of method pointers using the *full* name. + * For OpenVMS we therefor added this singleton class and the + * ACE_Dynamic_Svc_Registrar class which registers full names and function + * pointers with this singleton at the time the static ACE_Dynamic_Svc_Registrar + * object is created in a (service) DLL. + * By forcing the DLL to load using a common symbol ("NULL") we trigger static + * object creation *before* the full names are referenced. + * Symbol references will be resolved as follows on OpenVMS: + * - first try directly from DLL using the RTL dlsym() function and if that fails; + * - try to find symbol in singleton registry. + */ +class ACE_LD_Symbol_Registry +{ +public: + + typedef ACE_RB_Tree<const ACE_TCHAR*, + void*, + ACE_Less_Than<const ACE_TCHAR*>, + ACE_Thread_Mutex> + TREE; + + void register_symbol (const ACE_TCHAR* symname, void* symaddr); + + void* find_symbol (const ACE_TCHAR* symname); + + ACE_LD_Symbol_Registry () {} +private: + + TREE symbol_registry_; +}; + +void +ACE_LD_Symbol_Registry::register_symbol (const ACE_TCHAR* symname, + void* symaddr) +{ + int const result = symbol_registry_.bind (symname, symaddr); + if (result == 1) + { + ACE_DEBUG((LM_INFO, ACE_TEXT ("ACE_LD_Symbol_Registry:") + ACE_TEXT (" duplicate symbol %s registered\n"), + ACE_TEXT_ALWAYS_CHAR (symname))); + } + else if (result == -1) + { + ACE_ERROR((LM_ERROR, ACE_TEXT ("ACE_LD_Symbol_Registry:") + ACE_TEXT (" failed to register symbol %s\n"), + ACE_TEXT_ALWAYS_CHAR (symname))); + } +} + +void* +ACE_LD_Symbol_Registry::find_symbol (const ACE_TCHAR* symname) +{ + void* symaddr = 0; + int const result = symbol_registry_.find (symname, symaddr); + + return (result == 0 ? symaddr : 0); +} + +/// Declare a process wide singleton +ACE_SINGLETON_DECLARE (ACE_Singleton, + ACE_LD_Symbol_Registry, + ACE_Thread_Mutex) + +typedef ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex> + ACE_LD_SYMBOL_REGISTRY; + +#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION) +template ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex> * + ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>::singleton_; +#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */ +#endif + +ACE_RCSID(ace, Lib_Find, "$Id: Lib_Find.cpp 85473 2009-06-01 08:09:31Z johnnyw $") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +int +ACE::ldfind (const ACE_TCHAR* filename, + ACE_TCHAR pathname[], + size_t maxpathnamelen) +{ + ACE_TRACE ("ACE::ldfind"); +#if defined (ACE_OPENVMS) + if (ACE_OS::strlen(filename) >= maxpathnamelen) + { + errno = ENOMEM; + return -1; + } + + dsc$descriptor nameDsc; + nameDsc.dsc$b_class = DSC$K_CLASS_S; + nameDsc.dsc$b_dtype = DSC$K_DTYPE_T; + nameDsc.dsc$w_length = ACE_OS::strlen(filename); + nameDsc.dsc$a_pointer = (char*)filename; + + char symbol[] = "NULL"; + dsc$descriptor symbolDsc; + symbolDsc.dsc$b_class = DSC$K_CLASS_S; + symbolDsc.dsc$b_dtype = DSC$K_DTYPE_T; + symbolDsc.dsc$w_length = ACE_OS::strlen(symbol); + symbolDsc.dsc$a_pointer = symbol; + + int symbolValue; + int result; + try + { + result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0); + } + catch (chf$signal_array& sig) + { + result = sig.chf$l_sig_name; + } + + int severity = result & STS$M_SEVERITY; + int conditionId = result & STS$M_COND_ID; + if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO || + (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID))) + { + ACE_OS::strcpy(pathname, filename); + return 0; + } + + if (ACE_OS::strlen(filename) + ACE_OS::strlen(ACE_DLL_PREFIX) >= maxpathnamelen) + { + errno = ENOMEM; + return -1; + } + + + ACE_OS::strcpy(pathname, ACE_DLL_PREFIX); + ACE_OS::strcat(pathname, filename); + nameDsc.dsc$w_length = ACE_OS::strlen(pathname); + nameDsc.dsc$a_pointer = pathname; + try + { + result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0); + } + catch (chf$signal_array& sig) + { + result = sig.chf$l_sig_name; + } + + severity = result & STS$M_SEVERITY; + conditionId = result & STS$M_COND_ID; + if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO || + (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID))) + { + return 0; + } + errno = ENOENT; + return -1; +#endif /* ACE_OPENVMS */ + +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && \ + !defined (ACE_HAS_PHARLAP) + ACE_TCHAR expanded_filename[MAXPATHLEN]; + if (ACE_TEXT_ExpandEnvironmentStrings (filename, + expanded_filename, + sizeof expanded_filename + / sizeof (ACE_TCHAR))) + filename = expanded_filename; +#endif /* ACE_WIN32 && !ACE_HAS_WINCE && !ACE_HAS_PHARLAP */ + + ACE_TCHAR tempcopy[MAXPATHLEN + 1]; + ACE_TCHAR searchpathname[MAXPATHLEN + 1]; +#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) + ACE_TCHAR decorator[] = ACE_LD_DECORATOR_STR; + ACE_TCHAR searchfilename[MAXPATHLEN + sizeof(decorator) / sizeof (ACE_TCHAR)]; +#else + ACE_TCHAR searchfilename[MAXPATHLEN + 1]; +#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */ + + // Create a copy of filename to work with. + if (ACE_OS::strlen (filename) + 1 + > (sizeof tempcopy / sizeof (ACE_TCHAR))) + { + errno = ENOMEM; + return -1; + } + else + ACE_OS::strcpy (tempcopy, filename); + + // Insert canonical directory separators. + ACE_TCHAR *separator_ptr; + +#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/') + // Make all the directory separators "canonical" to simplify + // subsequent code. + ACE::strrepl (tempcopy, ACE_DIRECTORY_SEPARATOR_CHAR, '/'); +#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */ + + // Separate filename from pathname. + separator_ptr = ACE_OS::strrchr (tempcopy, '/'); + + // This is a relative path. + if (separator_ptr == 0) + { + searchpathname[0] = '\0'; + ACE_OS::strcpy (searchfilename, tempcopy); + } + else // This is an absolute path. + { + ACE_OS::strcpy (searchfilename, separator_ptr + 1); + separator_ptr[1] = '\0'; + ACE_OS::strcpy (searchpathname, tempcopy); + } + + bool has_suffix = false; + + // Check to see if this has an appropriate DLL suffix for the OS + // platform. + ACE_TCHAR *s = ACE_OS::strrchr (searchfilename, '.'); + + const ACE_TCHAR *dll_suffix = ACE_DLL_SUFFIX; + + if (s != 0) + { + // If we have a dot, we have a suffix + has_suffix = true; + + // Check whether this matches the appropriate platform-specific + // suffix. +#if defined (ACE_WIN32) + // Use <ACE_OS::strcasecmp> on any platform with + // case-insensitive filenames. + if (ACE_OS::strcasecmp (s, dll_suffix) != 0) +#else + if (ACE_OS::strcmp (s, dll_suffix) != 0) +#endif /* ACE_WIN32 */ + { + ACE_ERROR ((LM_WARNING, + ACE_TEXT ("Warning: improper suffix for a ") + ACE_TEXT ("shared library on this platform: %s\n"), + s)); + } + } + + // Make sure we've got enough space in searchfilename. + if (ACE_OS::strlen (searchfilename) + + ACE_OS::strlen (ACE_DLL_PREFIX) + + (has_suffix ? 0 : ACE_OS::strlen (dll_suffix)) + >= (sizeof searchfilename / sizeof (ACE_TCHAR))) + { + errno = ENOMEM; + return -1; + } + +#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) + size_t const len_searchfilename = ACE_OS::strlen (searchfilename); + if (!has_suffix) + ACE_OS::strcpy (searchfilename + len_searchfilename, decorator); + + for (int tag = 1; tag >= 0; tag --) + { + if (tag == 0) + searchfilename [len_searchfilename] = 0; + +#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */ + // Use absolute pathname if there is one. + if (ACE_OS::strlen (searchpathname) > 0) + { + if (ACE_OS::strlen (searchfilename) + + ACE_OS::strlen (searchpathname) >= maxpathnamelen) + { + errno = ENOMEM; + return -1; + } + else + { +#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/') + // Revert to native path name separators. + ACE::strrepl (searchpathname, + '/', + ACE_DIRECTORY_SEPARATOR_CHAR); +#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */ + // First, try matching the filename *without* adding a + // prefix. + ACE_OS::sprintf (pathname, + ACE_TEXT ("%s%s%s"), + searchpathname, + searchfilename, + has_suffix ? ACE_TEXT ("") : dll_suffix); + if (ACE_OS::access (pathname, F_OK) == 0) + return 0; + + // Second, try matching the filename *with* adding a prefix. + ACE_OS::sprintf (pathname, + ACE_TEXT ("%s%s%s%s"), + searchpathname, + ACE_DLL_PREFIX, + searchfilename, + has_suffix ? ACE_TEXT ("") : dll_suffix); + if (ACE_OS::access (pathname, F_OK) == 0) + return 0; + } + } + + // Use relative filenames via LD_LIBRARY_PATH or PATH (depending on + // OS platform). + else + { +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_TCHAR *file_component = 0; + DWORD pathlen = + ACE_TEXT_SearchPath (0, + searchfilename, + dll_suffix, + static_cast<DWORD> (maxpathnamelen), + pathname, + &file_component); + if (pathlen >= maxpathnamelen) + { + errno = ENOMEM; + return -1; + } + else if (pathlen > 0) + return 0; + + // In case not found we should try again with the ACE_DLL_PREFIX + // prefixed + ACE_OS::strcpy (searchfilename, ACE_DLL_PREFIX); + ACE_OS::strcat (searchfilename, tempcopy); + pathlen = + ACE_TEXT_SearchPath (0, + searchfilename, + dll_suffix, + static_cast<DWORD> (maxpathnamelen), + pathname, + &file_component); + if (pathlen >= maxpathnamelen) + { + errno = ENOMEM; + return -1; + } + else if (pathlen > 0) + return 0; +#else + ACE_TCHAR *ld_path = 0; +# if defined ACE_DEFAULT_LD_SEARCH_PATH + ld_path = const_cast <ACE_TCHAR*> (ACE_DEFAULT_LD_SEARCH_PATH); +# else +# if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) + ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH); +# else + // Wide-char, non-Windows only offers char * getenv. So capture + // it, translate to wide-char, and continue. + ACE_Ascii_To_Wide wide_ldpath + (ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (ACE_LD_SEARCH_PATH))); + ld_path = wide_ldpath.wchar_rep (); +# endif /* ACE_WIN32 || !ACE_USES_WCHAR */ +# endif /* ACE_DEFAULT_LD_SEARCH_PATH */ + +#if defined (ACE_HAS_WINCE) + ACE_TCHAR *ld_path_temp = 0; + if (ld_path != 0) + { + ld_path_temp = (ACE_TCHAR *) + ACE_OS::malloc ((ACE_OS::strlen (ld_path) + 2) + * sizeof (ACE_TCHAR)); + if (ld_path_temp != 0) + { + ACE_OS::strcpy (ld_path_temp, + ACE_LD_SEARCH_PATH_SEPARATOR_STR); + + ACE_OS::strcat (ld_path_temp, ld_path); + ld_path = ld_path_temp; + } + else + { + ACE_OS::free ((void *) ld_path_temp); + ld_path = ld_path_temp = 0; + } + } +#endif /* ACE_HAS_WINCE */ + + if (ld_path != 0 + && (ld_path = ACE_OS::strdup (ld_path)) != 0) + { + // strtok has the strange behavior of not separating the + // string ":/foo:/bar" into THREE tokens. One would expect + // that the first iteration the token would be an empty + // string, the second iteration would be "/foo", and the + // third iteration would be "/bar". However, this is not + // the case; one only gets two iterations: "/foo" followed + // by "/bar". + + // This is especially a problem in parsing Unix paths + // because it is permissible to specify 'the current + // directory' as an empty entry. So, we introduce the + // following special code to cope with this: + + // Look at each dynamic lib directory in the search path. + + ACE_TCHAR *nextholder = 0; + const ACE_TCHAR *path_entry = + ACE::strsplit_r (ld_path, + ACE_LD_SEARCH_PATH_SEPARATOR_STR, + nextholder); + int result = 0; + + for (;;) + { + // Check if at end of search path. + if (path_entry == 0) + { + errno = ENOENT; + result = -1; + break; + } + else if (ACE_OS::strlen (path_entry) + + 1 + + ACE_OS::strlen (searchfilename) + >= maxpathnamelen) + { + errno = ENOMEM; + result = -1; + break; + } + // This works around the issue where a path might have + // an empty component indicating 'current directory'. + // We need to do it here rather than anywhere else so + // that the loop condition will still work. + else if (path_entry[0] == '\0') + path_entry = ACE_TEXT ("."); + + // First, try matching the filename *without* adding a + // prefix. + ACE_OS::sprintf (pathname, + ACE_TEXT ("%s%c%s%s"), + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + searchfilename, + has_suffix ? ACE_TEXT ("") : dll_suffix); + if (ACE_OS::access (pathname, F_OK) == 0) + break; + + // Second, try matching the filename *with* adding a + // prefix. + ACE_OS::sprintf (pathname, + ACE_TEXT ("%s%c%s%s%s"), + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + ACE_DLL_PREFIX, + searchfilename, + has_suffix ? ACE_TEXT ("") : dll_suffix); + if (ACE_OS::access (pathname, F_OK) == 0) + break; + + // Fetch the next item in the path + path_entry = + ACE::strsplit_r (0, + ACE_LD_SEARCH_PATH_SEPARATOR_STR, + nextholder); + } + +#if defined (ACE_HAS_WINCE) + if (ld_path_temp != 0) + ACE_OS::free (ld_path_temp); +#endif /* ACE_HAS_WINCE */ + ACE_OS::free ((void *) ld_path); +#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) + if (result == 0 || tag == 0) +#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */ + return result; + } +#endif /* ACE_WIN32 && !ACE_HAS_WINCE */ + } +#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) + } +#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */ + + errno = ENOENT; + return -1; +} + +FILE * +ACE::ldopen (const ACE_TCHAR *filename, + const ACE_TCHAR *type) +{ + ACE_TRACE ("ACE::ldopen"); + + ACE_TCHAR buf[MAXPATHLEN + 1]; + if (ACE::ldfind (filename, + buf, + sizeof (buf) /sizeof (ACE_TCHAR)) == -1) + return 0; + else + return ACE_OS::fopen (buf, type); +} + +ACE_TCHAR * +ACE::ldname (const ACE_TCHAR *entry_point) +{ + ACE_TRACE ("ACE::ldname"); + +#if defined(ACE_NEEDS_DL_UNDERSCORE) + size_t size = + 1 // leading '_' + + ACE_OS::strlen (entry_point) + + 1; + + ACE_TCHAR *new_name; + ACE_NEW_RETURN (new_name, + ACE_TCHAR[size], + 0); + + ACE_OS::strcpy (new_name, ACE_TEXT ("_")); + ACE_OS::strcat (new_name, entry_point); + + return new_name; +#else /* ACE_NEEDS_DL_UNDERSCORE */ + size_t size = + ACE_OS::strlen (entry_point) + + 1; + + ACE_TCHAR *new_name; + ACE_NEW_RETURN (new_name, + ACE_TCHAR[size], + 0); + + ACE_OS::strcpy (new_name, entry_point); + return new_name; +#endif /* ACE_NEEDS_DL_UNDERSCORE */ +} + +#if defined (ACE_OPENVMS) +void +ACE::ldregister (const ACE_TCHAR *entry_point, + void* entry_addr) +{ + ACE_LD_SYMBOL_REGISTRY::instance ()->register_symbol (entry_point, + entry_addr); +} + +void * +ACE::ldsymbol (ACE_SHLIB_HANDLE sh, const ACE_TCHAR *entry_point) +{ + void* symaddr = ACE_OS::dlsym (sh, entry_point); + // if not found through dlsym() try registry + if (symaddr == 0) + symaddr = ACE_LD_SYMBOL_REGISTRY::instance ()->find_symbol (entry_point); + + return symaddr; +} +#endif + +int +ACE::get_temp_dir (ACE_TCHAR *buffer, size_t buffer_len) +{ + int result; +#if defined (ACE_WIN32) + result = ACE_TEXT_GetTempPath (static_cast<DWORD> (buffer_len), + buffer); + + // Make sure to return -1 if there is an error + if ((result == 0 && ::GetLastError () != ERROR_SUCCESS) + || (result > static_cast<int> (buffer_len))) + result = -1; + +#else /* ACE_WIN32 */ + + // NOTE! Non-Windows platforms don't deal with wide chars for env. + // variables, so do this narrow-char and convert to wide for the + // caller if necessary. + + // On non-win32 platforms, check to see what the TMPDIR environment + // variable is defined to be. If it doesn't exist, just use /tmp + const char *tmpdir = ACE_OS::getenv ("TMPDIR"); + + if (tmpdir == 0) + tmpdir = "/tmp"; + + size_t len = ACE_OS::strlen (tmpdir); + + // Check to see if the buffer is large enough for the string, + // another /, and its null character (hence the + 2) + if ((len + 2) > buffer_len) + { + result = -1; + } + else + { + ACE_OS::strcpy (buffer, ACE_TEXT_CHAR_TO_TCHAR (tmpdir)); + + // Add a trailing slash because we cannot assume there is already one + // at the end. And having an extra one should not cause problems. + buffer[len] = ACE_TEXT ('/'); + buffer[len + 1] = 0; + result = 0; + } +#endif /* ACE_WIN32 */ + return result; +} + +ACE_HANDLE +ACE::open_temp_file (const ACE_TCHAR *name, int mode, int perm) +{ +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (perm); + ACE_HANDLE handle = ACE_OS::open (name, + mode, + FILE_SHARE_READ + | FILE_SHARE_WRITE + | FILE_SHARE_DELETE); +#else + // Open it. + ACE_HANDLE handle = ACE_OS::open (name, mode, perm); +#endif /* ACE_WIN32 */ + + if (handle == ACE_INVALID_HANDLE) + return ACE_INVALID_HANDLE; + + // Unlink it so that the file will be removed automatically when the + // process goes away. + if (ACE_OS::unlink (name) == -1) + return ACE_INVALID_HANDLE; + else + // Return the handle. + return handle; +} + +size_t +ACE::strrepl (char *s, char search, char replace) +{ + ACE_TRACE ("ACE::strrepl"); + + size_t replaced = 0; + + for (size_t i = 0; s[i] != '\0'; i++) + if (s[i] == search) + { + s[i] = replace; + ++replaced; + } + + return replaced; +} + + +// Split a string up into 'token'-delimited pieces, ala Perl's +// "split". + +char * +ACE::strsplit_r (char *str, + const char *token, + char *&next_start) +{ + char *result = 0; + + if (str != 0) + next_start = str; + + if (next_start != 0) + { + char *tok_loc = ACE_OS::strstr (next_start, token); + + if (tok_loc != 0) + { + // Return the beginning of the string. + result = next_start; + + // Insure it's terminated. + *tok_loc = '\0'; + next_start = tok_loc + ACE_OS::strlen (token); + } + else + { + result = next_start; + next_start = (char *) 0; + } + } + + return result; +} + +#if defined (ACE_HAS_WCHAR) +wchar_t * +ACE::strsplit_r (wchar_t *str, + const wchar_t *token, + wchar_t *&next_start) +{ + wchar_t *result = 0; + + if (str != 0) + next_start = str; + + if (next_start != 0) + { + wchar_t *tok_loc = ACE_OS::strstr (next_start, token); + + if (tok_loc != 0) + { + // Return the beginning of the string. + result = next_start; + + // Insure it's terminated. + *tok_loc = '\0'; + next_start = tok_loc + ACE_OS::strlen (token); + } + else + { + result = next_start; + next_start = (wchar_t *) 0; + } + } + + return result; +} + +size_t +ACE::strrepl (wchar_t *s, wchar_t search, wchar_t replace) +{ + ACE_TRACE ("ACE::strrepl"); + + size_t replaced = 0; + + for (size_t i = 0; s[i] != '\0'; i++) + if (s[i] == search) + { + s[i] = replace; + ++replaced; + } + + return replaced; +} +#endif /* ACE_HAS_WCHAR */ + +ACE_END_VERSIONED_NAMESPACE_DECL |