1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates.
   3  * All rights reserved. Use is subject to license terms.
   4  *
   5  * This file is available and licensed under the following license:
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  *  - Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *  - Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in
  15  *    the documentation and/or other materials provided with the distribution.
  16  *  - Neither the name of Oracle Corporation nor the names of its
  17  *    contributors may be used to endorse or promote products derived
  18  *    from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 #include "PlatformString.h"
  35 
  36 #include "Java.h"
  37 #include "Helpers.h"
  38 
  39 #include <stdio.h>
  40 #include <stdlib.h>
  41 #include <stdlib.h>
  42 #include <memory.h>
  43 #include <sstream>
  44 #include <string.h>
  45 
  46 #include "jni.h"
  47 
  48 //--------------------------------------------------------------------------------------------------
  49 
  50 #ifdef MAC
  51 StringToFileSystemString::StringToFileSystemString(const TString &value) {
  52     FRelease = false;
  53     PlatformString lvalue = PlatformString(value);
  54     Platform& platform = Platform::GetInstance();
  55     FData = platform.ConvertStringToFileSystemString(lvalue, FRelease);
  56 }
  57 
  58 StringToFileSystemString::~StringToFileSystemString() {
  59     if (FRelease == true) {
  60         delete[] FData;
  61     }
  62 }
  63 
  64 StringToFileSystemString::operator TCHAR* () {
  65     return FData;
  66 }
  67 #endif //MAC
  68 
  69 //--------------------------------------------------------------------------------------------------
  70 
  71 #ifdef MAC
  72 FileSystemStringToString::FileSystemStringToString(const TCHAR* value) {
  73     bool release = false;
  74     PlatformString lvalue = PlatformString(value);
  75     Platform& platform = Platform::GetInstance();
  76     TCHAR* buffer = platform.ConvertFileSystemStringToString(lvalue, release);
  77     FData = buffer;
  78     
  79     if (buffer != NULL && release == true) {
  80         delete[] buffer;
  81     }
  82 }
  83 
  84 FileSystemStringToString::operator TString () {
  85     return FData;
  86 }
  87 #endif //MAC
  88 
  89 
  90 //--------------------------------------------------------------------------------------------------
  91 
  92 
  93 void PlatformString::initialize() {
  94     FWideTStringToFree = NULL;
  95     FLength = 0;
  96     FData = NULL;
  97 }
  98 
  99 void PlatformString::CopyString(char *Destination, size_t NumberOfElements, const char *Source) {
 100 #ifdef WINDOWS
 101     strcpy_s(Destination, NumberOfElements, Source);
 102 #endif //WINDOWS
 103 #ifdef POSIX
 104     strncpy(Destination, Source, NumberOfElements);
 105 #endif //POSIX
 106 
 107     if (NumberOfElements > 0) {
 108         Destination[NumberOfElements - 1] = '\0';
 109     }
 110 }
 111 
 112 void PlatformString::CopyString(wchar_t *Destination, size_t NumberOfElements, const wchar_t *Source) {
 113 #ifdef WINDOWS
 114     wcscpy_s(Destination, NumberOfElements, Source);
 115 #endif //WINDOWS
 116 #ifdef POSIX
 117     wcsncpy(Destination, Source, NumberOfElements);
 118 #endif //POSIX
 119     
 120     if (NumberOfElements > 0) {
 121         Destination[NumberOfElements - 1] = '\0';
 122     }
 123 }
 124 
 125 PlatformString::PlatformString(void) {
 126     initialize();
 127 }
 128 
 129 PlatformString::~PlatformString(void) {
 130     if (FData != NULL) {
 131         delete[] FData;
 132     }
 133 
 134     if (FWideTStringToFree != NULL) {
 135         delete[] FWideTStringToFree;
 136     }
 137 }
 138 
 139 // Owner must free the return value.
 140 MultibyteString PlatformString::WideStringToMultibyteString(const wchar_t* value) {
 141     MultibyteString result;
 142     size_t count = 0;
 143 
 144 #ifdef WINDOWS
 145     wcstombs_s(&count, NULL, 0, value, 0);
 146 
 147     if (count > 0) {
 148         result.data = new char[count + 1];
 149         wcstombs_s(&result.length, result.data, count, value, count);
 150 
 151 #endif //WINDOWS
 152 #ifdef POSIX
 153     count = wcstombs(NULL, value, 0);
 154 
 155     if (count > 0) {
 156         result.data = new char[count + 1];
 157         result.data[count] = '\0';
 158         result.length = count;
 159         wcstombs(result.data, value, count);
 160 #endif //POSIX
 161     }
 162 
 163     return result;
 164 }
 165 
 166 // Owner must free the return value.
 167 WideString PlatformString::MultibyteStringToWideString(const char* value) {
 168     WideString result;
 169     size_t count = 0;
 170 
 171 #ifdef WINDOWS
 172     mbstowcs_s(&count, NULL, 0, value, _TRUNCATE);
 173 
 174     if (count > 0) {
 175         result.data = new wchar_t[count + 1];
 176         mbstowcs_s(&result.length, result.data, count, value, count);
 177 #endif // WINDOWS
 178 #ifdef POSIX
 179     count = mbstowcs(NULL, value, 0);
 180 
 181     if (count > 0) {
 182         result.data = new wchar_t[count + 1];
 183         result.data[count] = '\0';
 184         result.length = count;
 185         mbstowcs(result.data, value, count);
 186 #endif //POSIX
 187     }
 188 
 189     return result;
 190 }
 191 
 192 PlatformString::PlatformString(const PlatformString &value) {
 193     initialize();
 194     FLength = value.FLength;
 195     FData = new char[FLength + 1];
 196     PlatformString::CopyString(FData, FLength + 1, value.FData);
 197 }
 198 
 199 PlatformString::PlatformString(const char* value) {
 200     initialize();
 201     FLength = strlen(value);
 202     FData = new char[FLength + 1];
 203     PlatformString::CopyString(FData, FLength + 1, value);
 204 }
 205 
 206 PlatformString::PlatformString(size_t Value) {
 207     initialize();
 208     
 209     std::stringstream ss;
 210     std::string s;
 211     ss << Value;
 212     s = ss.str();
 213     
 214     FLength = strlen(s.c_str());
 215     FData = new char[FLength + 1];
 216     PlatformString::CopyString(FData, FLength + 1, s.c_str());
 217 }
 218     
 219 PlatformString::PlatformString(const wchar_t* value) {
 220     initialize();
 221     MultibyteString temp = WideStringToMultibyteString(value);
 222     FLength = temp.length;
 223     FData = temp.data;
 224 }
 225 
 226 PlatformString::PlatformString(const std::string &value) {
 227     initialize();
 228     const char* lvalue = value.data();
 229     FLength = value.size();
 230     FData = new char[FLength + 1];
 231     PlatformString::CopyString(FData, FLength + 1, lvalue);
 232 }
 233 
 234 PlatformString::PlatformString(const std::wstring &value) {
 235     initialize();
 236     const wchar_t* lvalue = value.data();
 237     MultibyteString temp = WideStringToMultibyteString(lvalue);
 238     FLength = temp.length;
 239     FData = temp.data;
 240 }
 241 
 242 PlatformString::PlatformString(JNIEnv *env, jstring value) {
 243     initialize();
 244 
 245     if (env != NULL) {
 246         const char* lvalue = env->GetStringUTFChars(value, JNI_FALSE);
 247 
 248         if (lvalue == NULL || env->ExceptionCheck() == JNI_TRUE) {
 249             throw JavaException();
 250         }
 251 
 252         if (lvalue != NULL) {
 253             FLength = env->GetStringUTFLength(value);
 254 
 255             if (env->ExceptionCheck() == JNI_TRUE) {
 256                 throw JavaException();
 257             }
 258 
 259             FData = new char[FLength + 1];
 260             PlatformString::CopyString(FData, FLength + 1, lvalue);
 261 
 262             env->ReleaseStringUTFChars(value, lvalue);
 263 
 264             if (env->ExceptionCheck() == JNI_TRUE) {
 265                 throw JavaException();
 266             }
 267         }
 268     }
 269 }
 270 
 271 std::string PlatformString::Format(std::string value, ...) {
 272     std::string result = value;
 273 
 274     va_list arglist;
 275     va_start(arglist, value);
 276 
 277     while (1) {
 278         size_t pos = result.find("%s", 0);
 279 
 280         if (pos == TString::npos) {
 281             break;
 282         }
 283         else {
 284             char* arg = va_arg(arglist, char*);
 285 
 286             if (arg == NULL) {
 287                 break;
 288             }
 289             else {
 290                 result.replace(pos, strlen("%s"), arg);
 291             }
 292         }
 293     }
 294 
 295     va_end(arglist);
 296 
 297     return result;
 298 }
 299 
 300 size_t PlatformString::length() {
 301     return FLength;
 302 }
 303 
 304 char* PlatformString::c_str() {
 305     return FData;
 306 }
 307 
 308 char* PlatformString::toMultibyte() {
 309     return FData;
 310 }
 311 
 312 wchar_t* PlatformString::toWideString() {
 313     WideString result = MultibyteStringToWideString(FData);
 314 
 315     if (result.data != NULL) {
 316         if (FWideTStringToFree != NULL) {
 317             delete [] FWideTStringToFree;
 318         }
 319 
 320         FWideTStringToFree = result.data;
 321     }
 322 
 323     return result.data;
 324 }
 325 
 326 std::wstring PlatformString::toUnicodeString() {
 327     std::wstring result;
 328     wchar_t* data = toWideString();
 329 
 330     if (FLength != 0 && data != NULL) {
 331         // NOTE: Cleanup of result is handled by PlatformString destructor.
 332         result = data;
 333     }
 334 
 335     return result;
 336 }
 337 
 338 std::string PlatformString::toStdString() {
 339     std::string result;
 340     char* data = toMultibyte();
 341 
 342     if (FLength > 0 && data != NULL) {
 343         result = data;
 344     }
 345 
 346     return result;
 347 }
 348 
 349 jstring PlatformString::toJString(JNIEnv *env) {
 350     jstring result = NULL;
 351 
 352     if (env != NULL) {
 353         result = env->NewStringUTF(c_str());
 354 
 355         if (result == NULL || env->ExceptionCheck() == JNI_TRUE) {
 356             throw JavaException();
 357         }
 358     }
 359 
 360     return result;
 361 }
 362 
 363 TCHAR* PlatformString::toPlatformString() {
 364 #ifdef _UNICODE
 365     return toWideString();
 366 #else
 367     return c_str();
 368 #endif //_UNICODE
 369 }
 370 
 371 TString PlatformString::toString() {
 372 #ifdef _UNICODE
 373     return toUnicodeString();
 374 #else
 375     return toStdString();
 376 #endif //_UNICODE
 377 }
 378 
 379 PlatformString::operator char* () {
 380     return c_str();
 381 }
 382 
 383 PlatformString::operator wchar_t* () {
 384     return toWideString();
 385 }
 386 
 387 PlatformString::operator std::wstring () {
 388     return toUnicodeString();
 389 }
 390 
 391 char* PlatformString::duplicate(const char* Value) {
 392     size_t length = strlen(Value);
 393     char* result = new char[length + 1];
 394     PlatformString::CopyString(result, length + 1, Value);
 395     return result;
 396 }
 397 
 398 wchar_t* PlatformString::duplicate(const wchar_t* Value) {
 399     size_t length = wcslen(Value);
 400     wchar_t* result = new wchar_t[length + 1];
 401     PlatformString::CopyString(result, length + 1, Value);
 402     return result;
 403 }