| 18 | #endif |
| 19 | |
| 20 | bool WideToChar(const wchar *Src,char *Dest,size_t DestSize) |
| 21 | { |
| 22 | bool RetCode=true; |
| 23 | *Dest=0; // Set 'Dest' to zero just in case the conversion will fail. |
| 24 | |
| 25 | #ifdef _WIN_ALL |
| 26 | if (WideCharToMultiByte(CP_ACP,0,Src,-1,Dest,(int)DestSize,NULL,NULL)==0) |
| 27 | RetCode=false; |
| 28 | |
| 29 | // wcstombs is broken in Android NDK r9. |
| 30 | #elif defined(_APPLE) |
| 31 | WideToUtf(Src,Dest,DestSize); |
| 32 | |
| 33 | #elif defined(MBFUNCTIONS) |
| 34 | if (!WideToCharMap(Src,Dest,DestSize,RetCode)) |
| 35 | { |
| 36 | mbstate_t ps; // Use thread safe external state based functions. |
| 37 | memset (&ps, 0, sizeof(ps)); |
| 38 | const wchar *SrcParam=Src; // wcsrtombs can change the pointer. |
| 39 | |
| 40 | // Some implementations of wcsrtombs can cause memory analyzing tools |
| 41 | // like valgrind to report uninitialized data access. It happens because |
| 42 | // internally these implementations call SSE4 based wcslen function, |
| 43 | // which reads 16 bytes at once including those beyond of trailing 0. |
| 44 | size_t ResultingSize=wcsrtombs(Dest,&SrcParam,DestSize,&ps); |
| 45 | |
| 46 | if (ResultingSize==(size_t)-1 && errno==EILSEQ) |
| 47 | { |
| 48 | // Aborted on inconvertible character not zero terminating the result. |
| 49 | // EILSEQ helps to distinguish it from small output buffer abort. |
| 50 | // We want to convert as much as we can, so we clean the output buffer |
| 51 | // and repeat conversion. |
| 52 | memset (&ps, 0, sizeof(ps)); |
| 53 | SrcParam=Src; // wcsrtombs can change the pointer. |
| 54 | memset(Dest,0,DestSize); |
| 55 | ResultingSize=wcsrtombs(Dest,&SrcParam,DestSize,&ps); |
| 56 | } |
| 57 | |
| 58 | if (ResultingSize==(size_t)-1) |
| 59 | RetCode=false; |
| 60 | if (ResultingSize==0 && *Src!=0) |
| 61 | RetCode=false; |
| 62 | } |
| 63 | #else |
| 64 | for (int I=0;I<DestSize;I++) |
| 65 | { |
| 66 | Dest[I]=(char)Src[I]; |
| 67 | if (Src[I]==0) |
| 68 | break; |
| 69 | } |
| 70 | #endif |
| 71 | if (DestSize>0) |
| 72 | Dest[DestSize-1]=0; |
| 73 | |
| 74 | // We tried to return the empty string if conversion is failed, |
| 75 | // but it does not work well. WideCharToMultiByte returns 'failed' code |
| 76 | // and partially converted string even if we wanted to convert only a part |
| 77 | // of string and passed DestSize smaller than required for fully converted |
no test coverage detected