udatamem.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. ******************************************************************************
  5. *
  6. * Copyright (C) 1999-2011, International Business Machines
  7. * Corporation and others. All Rights Reserved.
  8. *
  9. ******************************************************************************/
  10. /*----------------------------------------------------------------------------------
  11. *
  12. * UDataMemory A class-like struct that serves as a handle to a piece of memory
  13. * that contains some ICU data (resource, converters, whatever.)
  14. *
  15. * When an application opens ICU data (with udata_open, for example,
  16. * a UDataMemory * is returned.
  17. *
  18. *----------------------------------------------------------------------------------*/
  19. #include "unicode/utypes.h"
  20. #include "cmemory.h"
  21. #include "unicode/udata.h"
  22. #include "udatamem.h"
  23. U_CFUNC void UDataMemory_init(UDataMemory *This) {
  24. uprv_memset(This, 0, sizeof(UDataMemory));
  25. This->length=-1;
  26. }
  27. U_CFUNC void UDatamemory_assign(UDataMemory *dest, UDataMemory *source) {
  28. /* UDataMemory Assignment. Destination UDataMemory must be initialized first. */
  29. UBool mallocedFlag = dest->heapAllocated;
  30. uprv_memcpy(dest, source, sizeof(UDataMemory));
  31. dest->heapAllocated = mallocedFlag;
  32. }
  33. U_CFUNC UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) {
  34. UDataMemory *This;
  35. if (U_FAILURE(*pErr)) {
  36. return nullptr;
  37. }
  38. This = (UDataMemory *)uprv_malloc(sizeof(UDataMemory));
  39. if (This == nullptr) {
  40. *pErr = U_MEMORY_ALLOCATION_ERROR; }
  41. else {
  42. UDataMemory_init(This);
  43. This->heapAllocated = true;
  44. }
  45. return This;
  46. }
  47. U_CFUNC const DataHeader *
  48. UDataMemory_normalizeDataPointer(const void *p) {
  49. /* allow the data to be optionally prepended with an alignment-forcing double value */
  50. const DataHeader *pdh = (const DataHeader *)p;
  51. if(pdh==nullptr || (pdh->dataHeader.magic1==0xda && pdh->dataHeader.magic2==0x27)) {
  52. return pdh;
  53. } else {
  54. #if U_PLATFORM == U_PF_OS400
  55. /*
  56. TODO: Fix this once the compiler implements this feature. Keep in sync with genccode.c
  57. This is here because this platform can't currently put
  58. const data into the read-only pages of an object or
  59. shared library (service program). Only strings are allowed in read-only
  60. pages, so we use char * strings to store the data.
  61. In order to prevent the beginning of the data from ever matching the
  62. magic numbers we must skip the initial double.
  63. [grhoten 4/24/2003]
  64. */
  65. return (const DataHeader *)*((const void **)p+1);
  66. #else
  67. return (const DataHeader *)((const double *)p+1);
  68. #endif
  69. }
  70. }
  71. U_CFUNC void UDataMemory_setData (UDataMemory *This, const void *dataAddr) {
  72. This->pHeader = UDataMemory_normalizeDataPointer(dataAddr);
  73. }
  74. U_CAPI void U_EXPORT2
  75. udata_close(UDataMemory *pData) {
  76. if(pData!=nullptr) {
  77. uprv_unmapFile(pData);
  78. if(pData->heapAllocated ) {
  79. uprv_free(pData);
  80. } else {
  81. UDataMemory_init(pData);
  82. }
  83. }
  84. }
  85. U_CAPI const void * U_EXPORT2
  86. udata_getMemory(UDataMemory *pData) {
  87. if(pData!=nullptr && pData->pHeader!=nullptr) {
  88. return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader);
  89. } else {
  90. return nullptr;
  91. }
  92. }
  93. /**
  94. * Get the length of the data item if possible.
  95. * The length may be up to 15 bytes larger than the actual data.
  96. *
  97. * TODO Consider making this function public.
  98. * It would have to return the actual length in more cases.
  99. * For example, the length of the last item in a .dat package could be
  100. * computed from the size of the whole .dat package minus the offset of the
  101. * last item.
  102. * The size of a file that was directly memory-mapped could be determined
  103. * using some system API.
  104. *
  105. * In order to get perfect values for all data items, we may have to add a
  106. * length field to UDataInfo, but that complicates data generation
  107. * and may be overkill.
  108. *
  109. * @param pData The data item.
  110. * @return the length of the data item, or -1 if not known
  111. * @internal Currently used only in cintltst/udatatst.c
  112. */
  113. U_CAPI int32_t U_EXPORT2
  114. udata_getLength(const UDataMemory *pData) {
  115. if(pData!=nullptr && pData->pHeader!=nullptr && pData->length>=0) {
  116. /*
  117. * subtract the header size,
  118. * return only the size of the actual data starting at udata_getMemory()
  119. */
  120. return pData->length-udata_getHeaderSize(pData->pHeader);
  121. } else {
  122. return -1;
  123. }
  124. }
  125. /**
  126. * Get the memory including the data header.
  127. * Used in cintltst/udatatst.c
  128. * @internal
  129. */
  130. U_CAPI const void * U_EXPORT2
  131. udata_getRawMemory(const UDataMemory *pData) {
  132. if(pData!=nullptr && pData->pHeader!=nullptr) {
  133. return pData->pHeader;
  134. } else {
  135. return nullptr;
  136. }
  137. }
  138. U_CFUNC UBool UDataMemory_isLoaded(const UDataMemory *This) {
  139. return This->pHeader != nullptr;
  140. }