File: offname.cc

package info (click to toggle)
dcmtk 3.6.9-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 95,648 kB
  • sloc: ansic: 426,874; cpp: 318,177; makefile: 6,401; sh: 4,341; yacc: 1,026; xml: 482; lex: 321; perl: 277
file content (144 lines) | stat: -rw-r--r-- 3,484 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 *
 *  Copyright (C) 1997-2022, OFFIS e.V.
 *  All rights reserved.  See COPYRIGHT file for details.
 *
 *  This software and supporting documentation were developed by
 *
 *    OFFIS e.V.
 *    R&D Division Health
 *    Escherweg 2
 *    D-26121 Oldenburg, Germany
 *
 *
 *  Module: ofstd
 *
 *  Author: Marco Eichelberg
 *
 *  Purpose:
 *    classes: OFFilenameCreator
 *
 */

#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/offname.h"
#include "dcmtk/ofstd/ofcast.h"
#include "dcmtk/ofstd/ofstd.h"        /* for OFString::myrand_r */
#include "dcmtk/ofstd/ofstdinc.h"
#include <cerrno>
#include <ctime>


BEGIN_EXTERN_C
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>    /* for time_t */
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>    /* for stat() */
#endif
END_EXTERN_C

/* give up after this number of unsuccessful attempts to create a unique filename */
#define MAX_TRY 1024

OFFilenameCreator::OFFilenameCreator()
: creation_time(0)
{
  creation_time = OFstatic_cast(unsigned long, time(NULL));
}

OFFilenameCreator::OFFilenameCreator(const OFFilenameCreator& copy)
: creation_time(copy.creation_time)
{
}

OFFilenameCreator::~OFFilenameCreator()
{
}

OFFilenameCreator &OFFilenameCreator::operator=(const OFFilenameCreator& copy)
{
  creation_time = copy.creation_time;
  return *this;
}

OFBool OFFilenameCreator::makeFilename(unsigned int &seed, const char *dir, const char *prefix, const char *postfix, OFString &filename)
{
  OFBool done = OFFalse;
  OFBool result = OFTrue;
  struct stat stat_buf;
  int stat_result = 0;
  unsigned tries = 0;
  do
  {
    // create filename
    filename.clear();
    if (prefix) filename = prefix;
    addLongToString(creation_time, filename);
    // on some systems OFrand_r may produce only 16-bit random numbers.
    // To be on the safe side, we use two random numbers for the upper and the lower 16 bits.
    addLongToString((((OFrand_r(seed) & 0xFFFF) << 16) | (OFrand_r(seed) & 0xFFFF)), filename);
    if (postfix) filename += postfix;

    OFStandard::sanitizeFilename(filename);

    if (dir)
    {
      OFString dirname = dir;
      dirname += PATH_SEPARATOR;
      dirname += filename;
      filename = dirname;
    }

    // check if filename exists
    stat_result = stat(filename.c_str(), &stat_buf);
    if (stat_result == 0)
    {
      if (++tries == MAX_TRY)
      {
        done = OFTrue;
        result = OFFalse;
      }
    } else {
      // file does not exists, bail out
      done = OFTrue;
      if (errno != ENOENT) result=OFFalse; // something wrong with path
    }
  } while (!done);
  return result;
}


void OFFilenameCreator::addLongToString(unsigned long l, OFString &s)
{
  l &= 0xFFFFFFFFL;
  unsigned long m;
  int idx=7;
  char chr_array[9];
  OFStandard::strlcpy(chr_array, "00000000", 9);
  while (l)
  {
    m = l & 0x0FL;
    l >>= 4;
    if (m > 9)
        chr_array[idx--] = OFstatic_cast(char, 'a'+(m-10));
        else chr_array[idx--] = OFstatic_cast(char, '0'+m);
  }
  s += chr_array;
  return;
}

unsigned int OFFilenameCreator::hashString(const char *str)
{
  /* very simple hash function: XOR result with string character and rotate left by 1 bit. */
  unsigned int result = OFstatic_cast(unsigned int, -1);
  if (str)
  {
    while (*str != '\0')
    {
      result %= *str++;
      if (OFstatic_cast(signed int, result) <0) result = (result << 1)| 1; else result <<= 1;
    }
  }
  return result;
}