Convert and restore mapped inconvertible Unicode characters. We use it for extended ASCII names in Unix.
| 132 | // Convert and restore mapped inconvertible Unicode characters. |
| 133 | // We use it for extended ASCII names in Unix. |
| 134 | bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success) |
| 135 | { |
| 136 | // String with inconvertible characters mapped to private use Unicode area |
| 137 | // must have the mark code somewhere. |
| 138 | if (wcschr(Src,(wchar)MappedStringMark)==NULL) |
| 139 | return false; |
| 140 | |
| 141 | // Seems to be that wcrtomb in some memory analyzing libraries |
| 142 | // can produce uninitilized output while reporting success on garbage input. |
| 143 | // So we clean the destination to calm analyzers. |
| 144 | memset(Dest,0,DestSize); |
| 145 | |
| 146 | Success=true; |
| 147 | uint SrcPos=0,DestPos=0; |
| 148 | while (Src[SrcPos]!=0 && DestPos<DestSize-MB_CUR_MAX) |
| 149 | { |
| 150 | if (uint(Src[SrcPos])==MappedStringMark) |
| 151 | { |
| 152 | SrcPos++; |
| 153 | continue; |
| 154 | } |
| 155 | // For security reasons do not restore low ASCII codes, so mapping cannot |
| 156 | // be used to hide control codes like path separators. |
| 157 | if (uint(Src[SrcPos])>=MapAreaStart+0x80 && uint(Src[SrcPos])<MapAreaStart+0x100) |
| 158 | Dest[DestPos++]=char(uint(Src[SrcPos++])-MapAreaStart); |
| 159 | else |
| 160 | { |
| 161 | mbstate_t ps; |
| 162 | memset(&ps,0,sizeof(ps)); |
| 163 | if (wcrtomb(Dest+DestPos,Src[SrcPos],&ps)==(size_t)-1) |
| 164 | { |
| 165 | Dest[DestPos]='_'; |
| 166 | Success=false; |
| 167 | } |
| 168 | SrcPos++; |
| 169 | memset(&ps,0,sizeof(ps)); |
| 170 | int Length=mbrlen(Dest+DestPos,MB_CUR_MAX,&ps); |
| 171 | DestPos+=Max(Length,1); |
| 172 | } |
| 173 | } |
| 174 | Dest[Min(DestPos,DestSize-1)]=0; |
| 175 | return true; |
| 176 | } |
| 177 | #endif |
| 178 | |
| 179 |