// 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1.
const ui32_t VERSION_MAJOR = 1;
const ui32_t VERSION_APIMINOR = 1;
- const ui32_t VERSION_IMPMINOR = 7;
+ const ui32_t VERSION_IMPMINOR = 8;
const char* Version();
// UUIDs are passed around as strings of UUIDlen bytes
Result_t();
public:
- Result_t(long v, const char* l) : value(v), label(l) {}
+ static const Result_t& Find(long);
+
+ Result_t(long v, const char* l);
+ ~Result_t();
+
inline bool operator==(const Result_t& rhs) const { return value == rhs.value; }
inline bool operator!=(const Result_t& rhs) const { return value != rhs.value; }
inline bool Success() { return ( value >= 0 ); }
#ifdef KM_WIN32
typedef struct _stati64 fstat_t;
+#define S_IFLNK 0
+
// AFAIK, there is no iovec equivalent in the win32 API
struct iovec {
if ( KM_SUCCESS(do_stat(pathname, &info)) )
{
- if ( info.st_mode & S_IFREG )
+ if ( info.st_mode & ( S_IFREG|S_IFLNK ) )
return true;
}
if ( KM_SUCCESS(do_stat(pathname, &info)) )
{
- if ( info.st_mode & S_IFREG )
+ if ( info.st_mode & ( S_IFREG|S_IFLNK ) )
return(info.st_size);
}
if ( KM_SUCCESS(do_fstat(m_Handle, &info)) )
{
- if ( info.st_mode & S_IFREG )
+ if ( info.st_mode & ( S_IFREG|S_IFLNK ) )
return(info.st_size);
}
#endif
Kumu::ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size)
{
fsize_t fsize = 0;
- ui32_t read_size;
+ ui32_t read_size = 0;
FileReader File;
ByteString ReadBuf;
{
fsize = File.Size();
- if ( fsize > max_size )
+ if ( fsize > (Kumu::fpos_t)max_size )
return RESULT_ALLOC;
result = ReadBuf.Capacity((ui32_t)fsize);
}
+//
+Kumu::Result_t
+Kumu::WriteStringIntoFile(const char* filename, const std::string& inString)
+{
+ FileWriter File;
+ ui32_t write_count = 0;
+ KM_TEST_NULL_STR(filename);
+
+ Result_t result = File.OpenWrite(filename);
+
+ if ( KM_SUCCESS(result) )
+ result = File.Write((byte_t*)inString.c_str(), inString.length(), &write_count);
+
+ if ( KM_SUCCESS(result) && write_count != inString.length() )
+ return RESULT_WRITEFAIL;
+
+ return RESULT_OK;
+}
+
+
//------------------------------------------------------------------------------------------
//
bool PathIsDirectory(const char* pathname);
fsize_t FileSize(const char* pathname);
- // reads an entire file into a string
+ // Reads an entire file into a string.
Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 256 * Kilobyte);
+ // Writes a string to a file, overwrites the existing file if present.
+ Result_t WriteStringIntoFile(const char* filename, const std::string& inString);
+
//
class FileReader
{
#ifdef KM_WIN32
// make up a byte by sampling the perf counter LSB
-static byte_t get_perf_byte()
+static byte_t get_perf_byte(byte_t carry)
{
LARGE_INTEGER ticks;
- byte_t retval;
-
- for ( int i = 0; i < 8; i++ )
+ byte_t sha_buf[20];
+ SHA_CTX SHA;
+ SHA1_Init(&SHA);
+ SHA1_Update(&SHA, &carry, sizeof(byte_t));
+
+ for ( int i = 0; i < 128; i++ )
{
QueryPerformanceCounter(&ticks);
- retval |= (ticks.LowPart & 0x00000001) << i;
+ SHA1_Update(&SHA, &ticks.LowPart, sizeof(ticks.LowPart));
}
- return retval;
+ SHA1_Final(sha_buf, &SHA);
+
+ fprintf(stderr, "0x%02x ", sha_buf[0]);
+ return sha_buf[0];
}
#else // KM_WIN32
#ifdef KM_WIN32
for ( ui32_t i = 0; i < RNG_KEY_SIZE; i++ )
- rng_key[i] = get_perf_byte();
-
+ {
+ byte_t carry = ( i == 0 ) ? 0xa3 : rng_key[i-1];
+ rng_key[i] = get_perf_byte(carry);
+ }
#else // KM_WIN32
// on POSIX systems we simply read some seed from /dev/urandom
FileReader URandom;
#include <KM_log.h>
#include <ctype.h>
#include <list>
+#include <map>
#include <string>
+//------------------------------------------------------------------------------------------
+
+// Result_t Internals
+
+struct map_entry_t
+{
+ long rcode;
+ Kumu::Result_t* result;
+};
+
+const ui32_t MapMax = 512;
+const ui32_t MapSize = MapMax * (sizeof(struct map_entry_t));
+static bool s_MapInit = false;
+static struct map_entry_t s_ResultMap[MapSize];
+
+//
+const Kumu::Result_t&
+Kumu::Result_t::Find(long v)
+{
+ for ( ui32_t i = 0; s_ResultMap[i].result != 0 && i < MapMax; i++ )
+ {
+ if ( s_ResultMap[i].rcode == v )
+ return *s_ResultMap[i].result;
+ }
+
+ DefaultLogSink().Error("Unknown result code: %ld\n", v);
+ return RESULT_FAIL;
+}
+
+//
+Kumu::Result_t::Result_t(long v, const char* l) : value(v), label(l)
+{
+ assert(l);
+
+ if ( ! s_MapInit )
+ {
+ s_MapInit = true;
+ s_ResultMap[0].rcode = v;
+ s_ResultMap[0].result = this;
+ s_ResultMap[1].rcode = 0;
+ s_ResultMap[1].result = 0;
+ return;
+ }
+
+ ui32_t i = 0;
+ while ( s_ResultMap[i].result != 0 && i < MapMax )
+ {
+ i++;
+ if ( s_ResultMap[i].rcode == v )
+ return;
+ }
+
+ assert(i+2 < MapMax);
+
+ s_ResultMap[i].rcode = v;
+ s_ResultMap[i].result = this;
+ s_ResultMap[i+1].rcode = 0;
+ s_ResultMap[i+1].result = 0;
+ return;
+}
+
+Kumu::Result_t::~Result_t() {}
+
+
//------------------------------------------------------------------------------------------
return str_buf;
}
+//
+bool
+Kumu::Timestamp::DecodeString(const char* datestr)
+{
+ if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
+ || datestr[4] != '-'
+ || ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
+ || datestr[7] != '-'
+ || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) )
+ || datestr[10] != 'T'
+ || ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
+ || datestr[13] != ':'
+ || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) )
+ || datestr[16] != ':'
+ || ! ( isdigit(datestr[17]) && isdigit(datestr[18]) )
+ || ! ( datestr[19] == '-' || datestr[19] == '+' )
+ || ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
+ || datestr[22] != ':'
+ || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
+ return false;
+
+ // TODO -- test this!
+ Year = atoi(datestr);
+ Month = atoi(datestr + 5);
+ Day = atoi(datestr + 8);
+ Hour = atoi(datestr + 11);
+ Minute = atoi(datestr + 14);
+ Second = atoi(datestr + 17);
+
+ ui32_t TZ_hh = atoi(datestr + 20);
+ ui32_t TZ_mm = atoi(datestr + 23);
+
+ if ( TZ_mm != 0 )
+ DefaultLogSink().Error("Ignoring sub-hours timezone offset: %lu\n", TZ_mm);
+
+ if ( TZ_hh > 12 )
+ DefaultLogSink().Error("Ignoring large timezone offset: %s\n", (datestr+19));
+ else
+ AddHours(TZ_hh);
+
+ return true;
+}
+
//
bool
Kumu::Timestamp::HasValue() const
const char* EncodeString(char* str_buf, ui32_t buf_len) const;
// decode and set value from string formatted by EncodeString
- Result_t SetFromString(const char* datestr);
+ bool DecodeString(const char* datestr);
// add the given number of days or hours to the timestamp value. Values less than zero
// will cause the value to decrease