Skip to content

Commit

Permalink
Rewrite using external functions from ModelicaTime.c
Browse files Browse the repository at this point in the history
* Rewrite DateTime.'constructor'.fromEpoch to utilize ModelicaTime_localtime
* Rewrite DateTime.'String'.formatted to utilize ModelicaTime_strftime
* Rewrite DateTime.epoch to utilize ModelicaTime_difftime
* Add DateTime.'constructor'.fromString utilizing ModelicaTime_strptime

ModelicaTime.[ch] need to be integrated to ModelicaExternalC for later distribution. During development ModelicaTime.c is directly included by the external function declaration.
  • Loading branch information
beutlich committed Apr 11, 2020
1 parent d222ae1 commit afdafa9
Show file tree
Hide file tree
Showing 10 changed files with 998 additions and 133 deletions.
2 changes: 1 addition & 1 deletion Modelica/Resources/BuildProjects/autotools/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
lib_LTLIBRARIES = libzlib.la libModelicaExternalC.la libModelicaMatIO.la libModelicaIO.la libModelicaStandardTables.la
libModelicaExternalC_la_SOURCES = ../../C-Sources/ModelicaFFT.c ../../C-Sources/ModelicaInternal.c ../../C-Sources/ModelicaRandom.c ../../C-Sources/ModelicaStrings.c
libModelicaExternalC_la_SOURCES = ../../C-Sources/ModelicaFFT.c ../../C-Sources/ModelicaInternal.c ../../C-Sources/ModelicaRandom.c ../../C-Sources/ModelicaStrings.c ../../C-Sources/ModelicaTime.c
libModelicaExternalC_la_LIBADD = @LIBMATH@
libModelicaIO_la_SOURCES = ../../C-Sources/ModelicaIO.c
libModelicaIO_la_LIBADD = libModelicaMatIO.la
Expand Down
6 changes: 5 additions & 1 deletion Modelica/Resources/BuildProjects/gcc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ EXTC_OBJS = \
ModelicaFFT.o \
ModelicaInternal.o \
ModelicaRandom.o \
ModelicaStrings.o
ModelicaStrings.o \
ModelicaTime.o

TABLES_OBJS = \
ModelicaStandardTables.o \
Expand Down Expand Up @@ -93,6 +94,9 @@ ModelicaRandom.o: ../../C-Sources/ModelicaRandom.c
ModelicaStrings.o: ../../C-Sources/ModelicaStrings.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c -o $@ $<

ModelicaTime.o: ../../C-Sources/ModelicaTime.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c -o $@ $<

%.o: ../../C-Sources/zlib/%.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c -o $@ $<

Expand Down
210 changes: 210 additions & 0 deletions Modelica/Resources/C-Sources/ModelicaTime.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/* ModelicaTime.c - External functions for Modelica.Utilities.Time
Copyright (C) 2020, Modelica Association and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// TODO: Remove when ModelicaTime.c will become part of ModelicaExternalC
#if defined(DYMOSIM)
#pragma once
#endif

#include "ModelicaTime.h"

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include "ModelicaUtilities.h"
#if !defined(__APPLE_CC__)
#include "strptime.h"
#endif

#if !defined(NO_TIME)
time_t epoch(int sec, int min, int hour, int mday, int mon, int year) {
struct tm tlocal;
time_t calendarTime;

memset(&tlocal, 0, sizeof(struct tm));
tlocal.tm_sec = sec;
tlocal.tm_min = min;
tlocal.tm_hour = hour;
tlocal.tm_mday = mday;
tlocal.tm_mon = mon - 1;
tlocal.tm_year = year - 1900;

calendarTime = mktime(&tlocal);
if (-1 == calendarTime) {
ModelicaFormatError("Not possible to convert \"%4i-%02i-%02i %02i:%02i:%02i\" "
"to time_t type in local time zone.\n", year, mon, mday, hour, min, sec);
}
return calendarTime;
}
#endif

double ModelicaTime_difftime(int sec, int min, int hour, int mday, int mon,
int year, int refYear) {
/* Get elapsed seconds w.r.t. reference year */
#if defined(NO_TIME)
return 0.0;
#else
const time_t endTime = epoch(sec, min, hour, mday, mon, year);
if (1970 == refYear) {
/* Avoid calling mktime for New Year 1970 in local time zone */
const time_t startTime = epoch(0, 0, 0, 2, 1, 1970);
return difftime(endTime, startTime) + 86400.0;
}
else {
const time_t startTime = epoch(0, 0, 0, 1, 1, refYear);
return difftime(endTime, startTime);
}
#endif
}

void ModelicaTime_localtime(_Out_ int* ms, _Out_ int* sec, _Out_ int* min,
_Out_ int* hour, _Out_ int* mday, _Out_ int* mon,
_Out_ int* year, double seconds, int refYear) {
/* Convert elapsed seconds w.r.t. reference year */
#if defined(NO_TIME)
*ms = 0;
*sec = 0;
*min = 0;
*hour = 0;
*mday = 0;
*mon = 0;
*year = 0;
#else
struct tm* tlocal;
time_t calendarTime;
double intPartOfSeconds;
double fracPartOfSeconds;
#if defined(_POSIX_) || (defined(_MSC_VER) && _MSC_VER >= 1400)
struct tm tres;
#endif

fracPartOfSeconds = modf(seconds, &intPartOfSeconds);
calendarTime = (time_t)intPartOfSeconds;

if (1970 == refYear) {
/* Avoid calling mktime for New Year 1970 in local time zone */
calendarTime = calendarTime + epoch(0, 0, 0, 2, 1, 1970) - (time_t)86400;
}
else {
calendarTime = calendarTime + epoch(0, 0, 0, 1, 1, refYear);
}

#if defined(_POSIX_)
tlocal = localtime_r(&calendarTime, &tres); /* Time fields in local time zone */
#elif defined(_MSC_VER) && _MSC_VER >= 1400
localtime_s(&tres, &calendarTime); /* Time fields in local time zone */
tlocal = &tres;
#else
tlocal = localtime(&calendarTime); /* Time fields in local time zone */
#endif

/* Do not memcpy as you do not know which sizes are in the struct */
*ms = (int)(fracPartOfSeconds*1000.0 + 0.5);
*sec = tlocal->tm_sec;
*min = tlocal->tm_min;
*hour = tlocal->tm_hour;
*mday = tlocal->tm_mday;
*mon = 1 + tlocal->tm_mon; /* Correct for month starting at 1 */
*year = 1900 + tlocal->tm_year; /* Correct for 4-digit year */
#endif
}

_Ret_z_ const char* ModelicaTime_strftime(int sec, int min, int hour, int mday, int mon,
int year, _In_z_ const char* format, int _maxSize) {
/* Formatted time to string conversion */
#if defined(NO_TIME)
return "";
#else
size_t retLen;
struct tm* tlocal;
const size_t maxSize = (size_t)_maxSize;
char* timePtr = ModelicaAllocateString(maxSize);
time_t calendarTime = epoch(sec, min, hour, mday, mon, year);
#if defined(_POSIX_) || (defined(_MSC_VER) && _MSC_VER >= 1400)
struct tm tres;
#endif

#if defined(_POSIX_)
tlocal = localtime_r(&calendarTime, &tres); /* Time fields in local time zone */
#elif defined(_MSC_VER) && _MSC_VER >= 1400
localtime_s(&tres, &calendarTime); /* Time fields in local time zone */
tlocal = &tres;
#else
tlocal = localtime(&calendarTime); /* Time fields in local time zone */
#endif

retLen = strftime(timePtr, maxSize, format, tlocal);
if (retLen > 0 && retLen <= maxSize) {
return (const char*)timePtr;
}
else {
return "";
}
#endif
}

void ModelicaTime_strptime(_Out_ int* ms, _Out_ int* sec, _Out_ int* min,
_Out_ int* hour, _Out_ int* mday, _Out_ int* mon,
_Out_ int* year, _In_z_ const char* buf,
_In_z_ const char* format) {
/* Formatted string to time conversion */
#if defined(NO_TIME)
*ms = 0;
*sec = 0;
*min = 0;
*hour = 0;
*mday = 0;
*mon = 0;
*year = 0;
#else
struct tm tlocal;

memset(&tlocal, 0, sizeof(struct tm));
if (strptime(buf, format, &tlocal)) {
/* Do not memcpy as you do not know which sizes are in the struct */
*sec = tlocal.tm_sec;
*min = tlocal.tm_min;
*hour = tlocal.tm_hour;
*mday = tlocal.tm_mday;
*mon = 1 + tlocal.tm_mon; /* Correct for month starting at 1 */
*year = 1900 + tlocal.tm_year; /* Correct for 4-digit year */
}
else {
*sec = 0;
*min = 0;
*hour = 0;
*mday = 0;
*mon = 0;
*year = 0;
}
*ms = 0;
#endif
}
96 changes: 96 additions & 0 deletions Modelica/Resources/C-Sources/ModelicaTime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* ModelicaTime.h - External functions header for Modelica.Utilities.Time
Copyright (C) 2020, Modelica Association and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/* The following #define's are available.
NO_TIME : Functions localtime and mktime are not present
MODELICA_EXPORT: Prefix used for function calls. If not defined, blank is used
Useful definition:
- "__declspec(dllexport)" if included in a DLL and the
functions shall be visible outside of the DLL
*/

#ifndef MODELICA_TIME_H_
#define MODELICA_TIME_H_

#if !defined(MODELICA_EXPORT)
#if defined(__cplusplus)
#define MODELICA_EXPORT extern "C"
#else
#define MODELICA_EXPORT
#endif
#endif

/*
* Non-null pointers and esp. null-terminated strings need to be passed to
* external functions.
*
* The following macros handle nonnull attributes for GNU C and Microsoft SAL.
*/
#undef MODELICA_NONNULLATTR
#undef MODELICA_RETURNNONNULLATTR
#if defined(__GNUC__)
#define MODELICA_NONNULLATTR __attribute__((nonnull))
#if defined(__GNUC_MINOR__) && (__GNUC__ > 3 && __GNUC_MINOR__ > 8)
#define MODELICA_RETURNNONNULLATTR __attribute__((returns_nonnull))
#else
#define MODELICA_RETURNNONNULLATTR
#endif
#elif defined(__ATTR_SAL)
#define MODELICA_NONNULLATTR
#define MODELICA_RETURNNONNULLATTR _Ret_z_ /* _Ret_notnull_ and null-terminated */
#else
#define MODELICA_NONNULLATTR
#define MODELICA_RETURNNONNULLATTR
#endif
#if !defined(__ATTR_SAL)
#undef _In_z_
#undef _Out_
#undef _Ret_z_
#define _In_z_
#define _Out_
#define _Ret_z_
#endif

MODELICA_EXPORT double ModelicaTime_difftime(int sec, int min, int hour,
int mday, int mon, int year, int refYear);
MODELICA_EXPORT void ModelicaTime_localtime(_Out_ int* ms, _Out_ int* sec,
_Out_ int* min, _Out_ int* hour, _Out_ int* mday, _Out_ int* mon,
_Out_ int* year, double seconds, int refYear) MODELICA_NONNULLATTR;
MODELICA_EXPORT MODELICA_RETURNNONNULLATTR const char* ModelicaTime_strftime(
int sec, int min, int hour, int mday, int mon, int year,
_In_z_ const char* format, int _maxSize) MODELICA_NONNULLATTR;
MODELICA_EXPORT void ModelicaTime_strptime(_Out_ int* ms, _Out_ int* sec,
_Out_ int* min, _Out_ int* hour, _Out_ int* mday, _Out_ int* mon,
_Out_ int* year, _In_z_ const char* buf,
_In_z_ const char* format) MODELICA_NONNULLATTR;

#endif
3 changes: 2 additions & 1 deletion Modelica/Resources/C-Sources/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ to the following object libraries
ModelicaInternal.c
ModelicaRandom.c
ModelicaStrings.c
ModelicaTime.c
win32_dirent.c (for Visual C++ on Windows)

- ModelicaIO (.lib, .dll, .a, .so, depending on tool and OS) containing:
Expand Down Expand Up @@ -53,4 +54,4 @@ Additionally, a tool vendor has to provide library "lapack"
and this library should be used in the linker when a model is compiled
that uses this library in its library annotation.

January 05, 2018.
April 11, 2020.

0 comments on commit afdafa9

Please sign in to comment.