Coverage Report

Created: 2026-05-16 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libredwg/src/common.c
Line
Count
Source
1
/*****************************************************************************/
2
/*  LibreDWG - free implementation of the DWG file format                    */
3
/*                                                                           */
4
/*  Copyright (C) 2009-2025 Free Software Foundation, Inc.                   */
5
/*                                                                           */
6
/*  This library is free software, licensed under the terms of the GNU       */
7
/*  General Public License as published by the Free Software Foundation,     */
8
/*  either version 3 of the License, or (at your option) any later version.  */
9
/*  You should have received a copy of the GNU General Public License        */
10
/*  along with this program.  If not, see <http://www.gnu.org/licenses/>.    */
11
/*****************************************************************************/
12
13
/*
14
 * common.c: common data arrays
15
 * written by Felipe Castro
16
 * modified by Felipe CorrĂȘa da Silva Sances
17
 * modified by Rodrigo Rodrigues da Silva
18
 * modified by Reini Urban
19
 */
20
21
#include "config.h"
22
#define COMMON_C
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <assert.h>
27
#include <time.h>
28
#include <math.h>
29
#include <ctype.h>
30
#include "common.h"
31
#include "logging.h"
32
33
// See also
34
// http://devel.gvsig.org/sites/org.gvsig.dwg/2.0-SNAPSHOT/gvsig-base-library-pom/org.gvsig.dwg/xref/org/gvsig/dwg/lib/DwgFile.html
35
const struct dwg_versions dwg_versions[DWG_VERSIONS] = {
36
  /* r,          type,    hdr,    desc,         dwg_version, maint_rel_version
37
   */
38
  { R_INVALID, "invalid", "INVALI", "No DWG", 0, 0 },
39
  { R_1_1, "r1.1", "MC0.0", "MicroCAD Release 1.1", 0, 0 },
40
  { R_1_2, "r1.2", "AC1.2", "AutoCAD Release 1.2", 0, 0 },
41
  { R_1_3, "r1.3", "AC1.3", "AutoCAD Release 1.3", 1, 0 },
42
  { R_1_4, "r1.4", "AC1.40", "AutoCAD Release 1.4", 2, 0 },
43
  { R_2_0b, "r2.0b", "AC1.50", "AutoCAD 2.0 beta", 3, 0 }, // not seen
44
  { R_2_0, "r2.0", "AC1.50", "AutoCAD Release 2.0", 4, 0 },
45
  { R_2_10, "r2.10", "AC2.10", "AutoCAD Release 2.10", 5, 0 },
46
  { R_2_21, "r2.21", "AC2.21", "AutoCAD Release 2.21", 6, 0 },
47
  { R_2_22, "r2.22", "AC2.22", "AutoCAD Release 2.22", 7, 0 },
48
  { R_2_4, "r2.4", "AC1001", "AutoCAD Release 2.4", 8, 0 },
49
  { R_2_5, "r2.5", "AC1002", "AutoCAD Release 2.5", 9, 0 },
50
  { R_2_6, "r2.6", "AC1003", "AutoCAD Release 2.6", 10, 0 },
51
  { R_9, "r9", "AC1004", "AutoCAD Release 9", 0xb, 0 },
52
  { R_9c1, "r9c1", "AC1005", "AutoCAD Release 9c1", 0xc, 0 },
53
  { R_10, "r10", "AC1006", "AutoCAD Release 10", 0xd, 0 },
54
  { R_11b1, "r11b1", "AC1007", "AutoCAD 11 beta 1", 0xe, 0 },
55
  { R_11b2, "r11b2", "AC1008", "AutoCAD 11 beta 2", 0xf, 0 },
56
  { R_11, "r11", "AC1009", "AutoCAD Release 11/12 (LT R1/R2)", 0x10, 0 },
57
  { R_13b1, "r13b1", "AC1010", "AutoCAD pre-R13 a", 0x11, 0 },
58
  { R_13b2, "r13b2", "AC1011", "AutoCAD pre-R13 b", 0x12, 0 },
59
  { R_13, "r13", "AC1012", "AutoCAD Release 13", 0x13, 0 },
60
  { R_13c3, "r13c3", "AC1013", "AutoCAD Release 13c3", 0x14, 0x5 },
61
  { R_14, "r14", "AC1014", "AutoCAD Release 14", 0x15, 0 },
62
  { R_2000b, "r2000b", "AC1500", "AutoCAD 2000 beta", 0x16, 0 },
63
  { R_2000, "r2000", "AC1015", "AutoCAD Release 2000", 0x17, 0xf },
64
  { R_2000i, "r2000i", "AC1016", "AutoCAD Release 2000i", 0x17, 0xf },
65
  { R_2002, "r2002", "AC1017", "AutoCAD Release 2002", 0x17, 0xf },
66
  { R_2004a, "r2004a", "AC402a", "AutoCAD 2004 alpha a", 0x18, 0x68 },
67
  { R_2004b, "r2004b", "AC402b", "AutoCAD 2004 alpha b", 0x18, 0x68 },
68
  { R_2004c, "r2004c", "AC1018", "AutoCAD 2004 beta", 0x18, 0x68 },
69
  // (includes versions AC1019/0x19 and AC1020/0x1a)
70
  { R_2004, "r2004", "AC1018", "AutoCAD Release 2004", 0x19, 0x68 },
71
  //{ R_2005, "r2005", "AC1019", "AutoCAD 2005", 0x19, 0 }, // not seen
72
  //{ R_2006, "r2006", "AC1020", "AutoCAD 2006", 0x19, 0 }, // not seen
73
  { R_2007a, "r2007a", "AC701a", "AutoCAD 2007 alpha", 0x1a, 0x32 },
74
  { R_2007b, "r2007b", "AC1021", "AutoCAD 2007 beta", 0x1a, 0x32 },
75
  { R_2007, "r2007", "AC1021", "AutoCAD Release 2007", 0x1b, 0x32 },
76
  //{ R_2008, "r2008", "AC1022", "AutoCAD 2008", 0x1b, 0 }, // not seen
77
  //{ R_2009, "r2009", "AC1023", "AutoCAD 2009", 0x1b, 0 }, // not seen
78
  { R_2010b, "r2010b", "AC1024", "AutoCAD 2010 beta", 0x1c, 0x6d },
79
  { R_2010, "r2010", "AC1024", "AutoCAD Release 2010", 0x1d, 0x6d },
80
  //{ R_2011, "r2011", "AC1025", "AutoCAD 2011", 0x1d, 0 }, // not seen
81
  //{ R_2012, "r2012", "AC1026", "AutoCAD 2012", 0x1e, 0 }, // not seen
82
  { R_2013b, "r2013b", "AC1027", "AutoCAD 2013 beta", 0x1e, 0x7d },
83
  { R_2013, "r2013", "AC1027", "AutoCAD Release 2013", 0x1f, 0x7d },
84
  //{ R_2014, "r2014", "AC1028", "AutoCAD 2014", 0x1f, 0 }, // not seen
85
  //{ R_2015, "r2015", "AC1029", "AutoCAD 2015", 0x1f, 0 }, // not seen
86
  //{ R_2016, "r2016", "AC1030", "AutoCAD 2016", 0x1f, 0 }, // not seen
87
  //{ R_2017, "r2017", "AC1031", "AutoCAD 2017", 0x20, 0 }, // not seen
88
  { R_2018b, "r2018b", "AC1032", "AutoCAD 2018 beta", 0x20, 0x1d },
89
  { R_2018, "r2018", "AC1032", "AutoCAD Release 2018", 0x21, 0x1d },
90
  //{ R_2019, "r2019", "AC1033", "AutoCAD Release 2019", 0x22, 0 }, // not seen
91
  //{ R_2020, "r2020", "AC1034", "AutoCAD Release 2020", 0x23, 0 }, // not seen
92
  //{ R_2021, "r2021", "AC1035", "AutoCAD Release 2021", 0x23, 0 }, // not seen
93
  { R_2022b, "r2022b", "AC103-4", "AutoCAD 2022 beta", 0x24, 0x1d },
94
  { R_AFTER, "r>2022", NULL, "AutoCAD Release >2022", 0, 0 },
95
};
96
97
const unsigned char *
98
dwg_sentinel (const Dwg_Sentinel sentinel_id)
99
586
{
100
586
  static const unsigned char sentinels[DWG_SENTINEL_R11_AUXHEADER_END + 2][16]
101
586
      = { // DWG_SENTINEL_HEADER_END
102
586
          { 0x95, 0xA0, 0x4E, 0x28, 0x99, 0x82, 0x1A, 0xE5, 0x5E, 0x41, 0xE0,
103
586
            0x5F, 0x9D, 0x3A, 0x4D, 0x00 },
104
          // DWG_SENTINEL_THUMBNAIL_BEGIN
105
586
          { 0x1F, 0x25, 0x6D, 0x07, 0xD4, 0x36, 0x28, 0x28, 0x9D, 0x57, 0xCA,
106
586
            0x3F, 0x9D, 0x44, 0x10, 0x2B },
107
          // DWG_SENTINEL_THUMBNAIL_END
108
586
          { 0xE0, 0xDA, 0x92, 0xF8, 0x2B, 0xc9, 0xD7, 0xD7, 0x62, 0xA8, 0x35,
109
586
            0xC0, 0x62, 0xBB, 0xEF, 0xD4 },
110
          // DWG_SENTINEL_VARIABLE_BEGIN
111
586
          { 0xCF, 0x7B, 0x1F, 0x23, 0xFD, 0xDE, 0x38, 0xA9, 0x5F, 0x7C, 0x68,
112
586
            0xB8, 0x4E, 0x6D, 0x33, 0x5F },
113
          // DWG_SENTINEL_VARIABLE_END
114
586
          { 0x30, 0x84, 0xE0, 0xDC, 0x02, 0x21, 0xC7, 0x56, 0xA0, 0x83, 0x97,
115
586
            0x47, 0xB1, 0x92, 0xCC, 0xA0 },
116
          // DWG_SENTINEL_CLASS_BEGIN
117
586
          { 0x8D, 0xA1, 0xC4, 0xB8, 0xC4, 0xA9, 0xF8, 0xC5, 0xC0, 0xDC, 0xF4,
118
586
            0x5F, 0xE7, 0xCF, 0xB6, 0x8A },
119
          // DWG_SENTINEL_CLASS_END
120
586
          { 0x72, 0x5E, 0x3B, 0x47, 0x3B, 0x56, 0x07, 0x3A, 0x3F, 0x23, 0x0B,
121
586
            0xA0, 0x18, 0x30, 0x49, 0x75 },
122
          // DWG_SENTINEL_2NDHEADER_BEGIN
123
586
          { 0xD4, 0x7B, 0x21, 0xCE, 0x28, 0x93, 0x9F, 0xBF, 0x53, 0x24, 0x40,
124
586
            0x09, 0x12, 0x3C, 0xAA, 0x01 },
125
          // DWG_SENTINEL_2NDHEADER_END
126
586
          { 0x2B, 0x84, 0xDE, 0x31, 0xD7, 0x6C, 0x60, 0x40, 0xAC, 0xDB, 0xBF,
127
586
            0xF6, 0xED, 0xC3, 0x55, 0xFE },
128
          // DWG_SENTINEL_R11_ENTITIES_BEGIN C46E6854F86E3330633EC1852ADC9401
129
586
          { 0xC4, 0x6E, 0x68, 0x54, 0xF8, 0x6E, 0x33, 0x30, 0x63, 0x3E, 0xC1,
130
586
            0x85, 0x2A, 0xDC, 0x94, 0x01 },
131
          // DWG_SENTINEL_R11_ENTITIES_END   3B9197AB0791CCCF9CC13E7AD5236BFE
132
586
          { 0x3B, 0x91, 0x97, 0xAB, 0x07, 0x91, 0xCC, 0xCF, 0x9C, 0xC1, 0x3E,
133
586
            0x7A, 0xD5, 0x23, 0x6B, 0xFE },
134
          // DWG_SENTINEL_R11_BLOCK_BEGIN DBEFB3F0C73E6DA6C9B6245C4C6F32CB
135
586
          { 0xDB, 0xEF, 0xB3, 0xF0, 0xC7, 0x3E, 0x6D, 0xA6, 0xC9, 0xB6, 0x24,
136
586
            0x5C, 0x4C, 0x6F, 0x32, 0xCB },
137
          // DWG_SENTINEL_R11_BLOCK_END   24104C0F38C192593649DBA3B390CD34
138
586
          { 0x24, 0x10, 0x4C, 0x0F, 0x38, 0xC1, 0x92, 0x59, 0x36, 0x49, 0xDB,
139
586
            0xA3, 0xB3, 0x90, 0xCD, 0x34 },
140
          // DWG_SENTINEL_R11_LAYER_BEGIN 0EC4646FBB1DD38B0049C2EF18EA6FFB
141
586
          { 0x0E, 0xC4, 0x64, 0x6F, 0xBB, 0x1D, 0xD3, 0x8B, 0x00, 0x49, 0xC2,
142
586
            0xEF, 0x18, 0xEA, 0x6F, 0xFB },
143
          // DWG_SENTINEL_R11_LAYER_END   F13B9B9044E22C74FFB63D10E7159004
144
586
          { 0xF1, 0x3B, 0x9B, 0x90, 0x44, 0xE2, 0x2C, 0x74, 0xFF, 0xB6, 0x3D,
145
586
            0x10, 0xE7, 0x15, 0x90, 0x04 },
146
          // DWG_SENTINEL_R11_STYLE_BEGIN E23EC182439F617750ABC76696000618
147
586
          { 0xE2, 0x3E, 0xC1, 0x82, 0x43, 0x9F, 0x61, 0x77, 0x50, 0xAB, 0xC7,
148
586
            0x66, 0x96, 0x00, 0x06, 0x18 },
149
          // DWG_SENTINEL_R11_STYLE_END   1DC13E7DBC609E88AF54389969FFF9E7
150
586
          { 0x1D, 0xC1, 0x3E, 0x7D, 0xBC, 0x60, 0x9E, 0x88, 0xAF, 0x54, 0x38,
151
586
            0x99, 0x69, 0xFF, 0xF9, 0xE7 },
152
          // DWG_SENTINEL_R11_LTYPE_BEGIN AC901ACA1CBD951516164C14CE1888AF
153
586
          { 0xAC, 0x90, 0x1A, 0xCA, 0x1C, 0xBD, 0x95, 0x15, 0x16, 0x16, 0x4C,
154
586
            0x14, 0xCE, 0x18, 0x88, 0xAF },
155
          // DWG_SENTINEL_R11_LTYPE_END   536FE535E3426AEAE9E9B3EB31E77750
156
586
          { 0x53, 0x6F, 0xE5, 0x35, 0xE3, 0x42, 0x6A, 0xEA, 0xE9, 0xE9, 0xB3,
157
586
            0xEB, 0x31, 0xE7, 0x77, 0x50 },
158
          // DWG_SENTINEL_R11_VIEW_BEGIN  C13CAA5668F4B41E4B74F408424DBFA5
159
586
          { 0xC1, 0x3C, 0xAA, 0x56, 0x68, 0xF4, 0xB4, 0x1E, 0x4B, 0x74, 0xF4,
160
586
            0x08, 0x42, 0x4D, 0xBF, 0xA5 },
161
          // DWG_SENTINEL_R11_VIEW_END    3EC355A9970B4BE1B48B0BF7BDB2405A
162
586
          { 0x3E, 0xC3, 0x55, 0xA9, 0x97, 0x0B, 0x4B, 0xE1, 0xB4, 0x8B, 0x0B,
163
586
            0xF7, 0xBD, 0xB2, 0x40, 0x5A },
164
          // DWG_SENTINEL_R11_UCS_BEGIN   604AFA3D8490CC5BEFE7D6A57F1E61CD
165
586
          { 0x60, 0x4A, 0xFA, 0x3D, 0x84, 0x90, 0xCC, 0x5B, 0xEF, 0xE7, 0xD6,
166
586
            0xA5, 0x7F, 0x1E, 0x61, 0xCD },
167
          // DWG_SENTINEL_R11_UCS_END     9FB505C27B6F33A41018295A80E19E32
168
586
          { 0x9F, 0xB5, 0x05, 0xC2, 0x7B, 0x6F, 0x33, 0xA4, 0x10, 0x18, 0x29,
169
586
            0x5A, 0x80, 0xE1, 0x9E, 0x32 },
170
          // DWG_SENTINEL_R11_VPORT_BEGIN F6ED44612ADCE47B4EB92BBB6660638D
171
586
          { 0xF6, 0xED, 0x44, 0x61, 0x2A, 0xDC, 0xE4, 0x7B, 0x4E, 0xB9, 0x2B,
172
586
            0xBB, 0x66, 0x60, 0x63, 0x8D },
173
          // DWG_SENTINEL_R11_VPORT_END   0912BB9ED5231B84B146D444999F9C72
174
586
          { 0x09, 0x12, 0xBB, 0x9E, 0xD5, 0x23, 0x1B, 0x84, 0xB1, 0x46, 0xD4,
175
586
            0x44, 0x99, 0x9F, 0x9C, 0x72 },
176
          // DWG_SENTINEL_R11_APPID_BEGIN E125C25036686C0C3BD35D56C1791C3A
177
586
          { 0xE1, 0x25, 0xC2, 0x50, 0x36, 0x68, 0x6C, 0x0C, 0x3B, 0xD3, 0x5D,
178
586
            0x56, 0xC1, 0x79, 0x1C, 0x3A },
179
          // DWG_SENTINEL_R11_APPID_END   1EDA3DAFC99793F3C42CA2A93E86E3C5
180
586
          { 0x1E, 0xDA, 0x3D, 0xAF, 0xC9, 0x97, 0x93, 0xF3, 0xC4, 0x2C, 0xA2,
181
586
            0xA9, 0x3E, 0x86, 0xE3, 0xC5 },
182
          // DWG_SENTINEL_R11_DIMSTYLE_BEGIN B4183E42C99FFFE5B6E2CBB375C3C3B0
183
586
          { 0xB4, 0x18, 0x3E, 0x42, 0xC9, 0x9F, 0xFF, 0xE5, 0xB6, 0xE2, 0xCB,
184
586
            0xB3, 0x75, 0xC3, 0xC3, 0xB0 },
185
          // DWG_SENTINEL_R11_DIMSTYLE_END   4BE7C1BD3660001A491D344C8A3C3C4F
186
586
          { 0x4B, 0xE7, 0xC1, 0xBD, 0x36, 0x60, 0x00, 0x1A, 0x49, 0x1D, 0x34,
187
586
            0x4C, 0x8A, 0x3C, 0x3C, 0x4F },
188
          // DWG_SENTINEL_R11_VX_BEGIN    E0CA367CCEE7586F2B7D745505F1447F
189
586
          { 0xE0, 0xCA, 0x36, 0x7C, 0xCE, 0xE7, 0x58, 0x6F, 0x2B, 0x7D, 0x74,
190
586
            0x55, 0x05, 0xF1, 0x44, 0x7F },
191
          // DWG_SENTINEL_R11_VX_END      1F35C9833118A790D4828BAAFA0EBB80
192
586
          { 0x1F, 0x35, 0xC9, 0x83, 0x31, 0x18, 0xA7, 0x90, 0xD4, 0x82, 0x8B,
193
586
            0xAA, 0xFA, 0x0E, 0xBB, 0x80 },
194
          // DWG_SENTINEL_R11_BLOCK_ENTITIES_BEGIN
195
          // 722B7DEC3E8C886C7A720AFDC86C8426
196
586
          { 0x72, 0x2B, 0x7D, 0xEC, 0x3E, 0x8C, 0x88, 0x6C, 0x7A, 0x72, 0x0A,
197
586
            0xFD, 0xC8, 0x6C, 0x84, 0x26 },
198
          // DWG_SENTINEL_R11_BLOCK_ENTITIES_END
199
          // 8DD48213C1737793858DF50237937BD9
200
586
          { 0x8D, 0xD4, 0x82, 0x13, 0xC1, 0x73, 0x77, 0x93, 0x85, 0x8D, 0xF5,
201
586
            0x02, 0x37, 0x93, 0x7B, 0xD9 },
202
          // DWG_SENTINEL_R11_EXTRA_ENTITIES_BEGIN
203
          // D5F9D3BB0AA969A6CD1C87C7EE804B17
204
586
          { 0xD5, 0xF9, 0xD3, 0xBB, 0x0A, 0xA9, 0x69, 0xA6, 0xCD, 0x1C, 0x87,
205
586
            0xC7, 0xEE, 0x80, 0x4B, 0x17 },
206
          // DWG_SENTINEL_R11_EXTRA_ENTITIES_END
207
          // 2A062C44F556965932E37838117FB4E8
208
586
          { 0x2A, 0x06, 0x2C, 0x44, 0xF5, 0x56, 0x96, 0x59, 0x32, 0xE3, 0x78,
209
586
            0x38, 0x11, 0x7F, 0xB4, 0xE8 },
210
          // DWG_SENTINEL_R11_AUXHEADER_BEGIN 298DD149A9731FEA99DE32F94D0AE019
211
586
          { 0x29, 0x8D, 0xD1, 0x49, 0xA9, 0x73, 0x1F, 0xEA, 0x99, 0xDE, 0x32,
212
586
            0xF9, 0x4D, 0x0A, 0xE0, 0x19 },
213
          // DWG_SENTINEL_R11_AUXHEADER_END D6722EB6568CE0156621CD06B2F51FE6
214
586
          { 0xD6, 0x72, 0x2E, 0xB6, 0x56, 0x8C, 0xE0, 0x15, 0x66, 0x21, 0xCD,
215
586
            0x06, 0xB2, 0xF5, 0x1F, 0xE6 },
216
          // DWG_SENTINEL_ILLEGAL (used for memcmp)
217
586
          { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
218
586
            0xFE, 0xFE, 0xFE, 0xFE, 0xFE }
219
586
        };
220
586
  if ((unsigned)sentinel_id > DWG_SENTINEL_R11_AUXHEADER_END)
221
0
    {
222
0
      fprintf (stderr, "ERROR: Illegal sentinel_id %u\n",
223
0
               (unsigned)sentinel_id);
224
0
      return sentinels[DWG_SENTINEL_R11_AUXHEADER_END + 1];
225
0
    }
226
586
  return (const unsigned char *)sentinels[sentinel_id];
227
586
}
228
229
const struct dwg_versions *
230
dwg_version_struct (const Dwg_Version_Type version)
231
173
{
232
173
  if (version < R_AFTER)
233
173
    return &dwg_versions[version];
234
0
  else
235
0
    return NULL;
236
173
}
237
238
/* Returns the AC header magic string [6] */
239
const char *
240
dwg_version_codes (const Dwg_Version_Type version)
241
147
{
242
147
  if (version < R_AFTER)
243
147
    return dwg_versions[version].hdr;
244
0
  else
245
0
    return "------";
246
147
}
247
248
// map [rVER] to our enum number, not the dwg->header.dwgversion
249
// Acad 2018 offers SaveAs DWG: 2018,2013,2010,2007,2004,2000,r14
250
//                         DXF: 2018,2013,2010,2007,2004,2000,r12
251
// libdxfrw dwg2dxf offers R12, v2000, v2004, v2007, v2010
252
EXPORT Dwg_Version_Type
253
dwg_version_as (const char *version)
254
0
{
255
0
  for (int i = R_AFTER - 1; i > 0; i--)
256
0
    {
257
0
      if (strEQ (dwg_versions[i].type, version))
258
0
        return dwg_versions[i].r;
259
0
    }
260
0
  return R_INVALID;
261
0
}
262
263
/** The reverse of dwg_version_as (char*) */
264
EXPORT const char *
265
dwg_version_type (const Dwg_Version_Type version)
266
363
{
267
363
  if (version < R_AFTER)
268
363
    return dwg_versions[version].type;
269
0
  else
270
0
    return "invalid after";
271
363
}
272
273
/** The version from the magic char[6] header.
274
    The proper release must then be set when we read the dwg_version also. */
275
EXPORT Dwg_Version_Type
276
dwg_version_hdr_type (const char *hdr)
277
301
{
278
#ifndef HAVE_NONNULL
279
  if (!hdr)
280
    return R_INVALID;
281
#endif
282
7.16k
  for (int i = R_AFTER - 1; i > 0; i--)
283
7.14k
    {
284
7.14k
      if (strEQ (dwg_versions[i].hdr, hdr))
285
276
        return dwg_versions[i].r;
286
7.14k
    }
287
25
  return R_INVALID;
288
301
}
289
290
/** The version from the magic char[6] header and the matching dwg_version
291
 * number. */
292
Dwg_Version_Type
293
dwg_version_hdr_type2 (const char *hdr, unsigned dwg_version)
294
0
{
295
#ifndef HAVE_NONNULL
296
  if (!hdr)
297
    return R_INVALID;
298
#endif
299
0
  for (int i = R_AFTER - 1; i > 0; i--)
300
0
    {
301
0
      if (strEQ (dwg_versions[i].hdr, hdr))
302
0
        if (!dwg_version || dwg_versions[i].dwg_version == dwg_version)
303
0
          return dwg_versions[i].r;
304
0
    }
305
0
  return R_INVALID;
306
0
}
307
308
// keep in sync with common.h DWG_BITS
309
const char *dwg_bits_name[]
310
    = { "UNKNOWN", "RC",  "RS",  "RL",  "B",       "BB",  "3B",     "4BITS",
311
        "BS",      "BL",  "BLd", "RLL", "RD",      "BD",  "MC",     "UMC",
312
        "MS",      "TV",  "TU",  "T",   "TF",      "T32", "HANDLE", "BE",
313
        "DD",      "BT",  "BOT", "BLL", "TIMEBLL", "CMC", "ENC",    "2RD",
314
        "3RD",     "2BD", "3BD", "2DD", "3DD",     "CRC", "CRC64",  "RLLd" };
315
316
// minimal size of type in bits
317
// keep in sync with above
318
// used by unit-tests
319
const unsigned char dwg_bits_size[] = {
320
  0,   //"UNKNOWN",
321
  8,   //"RC",
322
  16,  //"RS",
323
  32,  //"RL",
324
  1,   //"B",
325
  2,   //"BB",
326
  3,   //"3B",
327
  4,   //"4BITS",
328
  2,   //"BS", 10,18
329
  2,   //"BL", 10,34
330
  2,   //"BLd", 10,34
331
  64,  //"RLL",
332
  64,  //"RD",
333
  2,   //"BD", 66
334
  1,   //"MC", 1-4
335
  1,   //"UMC", 1-4
336
  16,  //"MS", 32
337
  2,   //"TV",
338
  18,  //"TU",
339
  2,   //"T",
340
  1,   //"TF",
341
  2,   //"T32",
342
  4,   //"TU32",
343
  8,   //"HANDLE",
344
  1,   //"BE", or 3BD
345
  2,   //"DD",
346
  1,   //"BT",
347
  10,  //"BOT",
348
  3,   //"BLL",
349
  4,   //"TIMEBLL", 2xBL
350
  2,   //"CMC", r2004+: +2
351
  4,   //"ENC", r2004+
352
  128, //"2RD",
353
  196, //"3RD",
354
  4,   //"2BD",
355
  6,   //"3BD",
356
  4,   //"2DD",
357
  6,   //"3DD",
358
  8,   //"CRC",
359
  64,  //"CRC64",
360
  64,  //"RLLd",
361
};
362
363
/* replace from ("[rcount1]") with to ("[%d]") in s (e.g.
364
   "ref[rcount1].classname"). s is a global constant (#nam), so we cannot
365
   change it in-place.
366
 */
367
EXPORT char *
368
strrplc (const char *s, const char *from, const char *to)
369
0
{
370
0
  const char *p = strstr (s, from);
371
0
  if (p)
372
0
    {
373
0
      const size_t l1 = strlen (from);
374
0
      const size_t l2 = strlen (to);
375
0
      char *dest = (char *)calloc (1, 80);
376
0
      long i = p - s;
377
0
      assert (strlen (s) - ((long)l1 - l2) < 80);
378
0
      memcpy (dest, s, i);
379
0
      strncat (dest, to, 79 - l2);
380
0
      strncat (dest, s + i + l1, 79 - l1);
381
0
      return dest;
382
0
    }
383
0
  else
384
0
    return NULL;
385
0
}
386
387
// naive from scratch implementation, not from glibc.
388
// see also examples/unknown.c:membits
389
void *__nonnull ((1, 3))
390
    my_memmem (const void *h0, size_t k, const void *n0, size_t l)
391
0
{
392
0
  const unsigned char *h = h0, *n = n0;
393
0
  unsigned char *plast;
394
395
0
  if (!l)
396
0
    return (void *)h; // empty needle
397
0
  if (k < l)
398
0
    return NULL; // needle longer than haystack
399
0
  h = memchr (h0, *n, k);
400
0
  if (!h || l == 1)
401
0
    return (void *)h; // first needle char not found
402
0
  k -= h - (const unsigned char *)h0;
403
0
  if (k < l)
404
0
    return NULL; // no room for needle
405
406
0
  plast = (unsigned char *)h + (k - l);
407
0
  do // naive 2 loops: O(n^2)
408
0
    {
409
0
      size_t i = 0;
410
0
      while (h[i] == n[i])
411
0
        {
412
0
          if (++i == l)
413
0
            return (void *)h;
414
0
        }
415
0
    }
416
0
  while (++h <= plast);
417
0
  return NULL;
418
0
}
419
420
/*
421
 32 types, with 3 categories: Face, Edge, Display, plus 58 props r2013+
422
 */
423
const char *const _dwg_VISUALSTYLE_types[32] = { "Flat",
424
                                                 "FlatWithEdges",
425
                                                 "Gouraud",
426
                                                 "GouraudWithEdges",
427
                                                 "2DWireframe",
428
                                                 "3DWireFrame",
429
                                                 "Hidden",
430
                                                 "Basic",
431
                                                 "Realistic",
432
                                                 "Conceptual",
433
                                                 "Dim",
434
                                                 "Brighten",
435
                                                 "Thicken",
436
                                                 "LinePattern",
437
                                                 "Facepattern",
438
                                                 "ColorChange",
439
                                                 "FaceOnly",
440
                                                 "EdgeOnly",
441
                                                 "DisplayOnly",
442
                                                 "JitterOff",
443
                                                 "OverhangOff",
444
                                                 "EdgeColorOff",
445
                                                 "Shades of Gray",
446
                                                 "Sketchy",
447
                                                 "X-Ray",
448
                                                 "Shaded with edges",
449
                                                 "Shaded",
450
                                                 "ByViewport",
451
                                                 "ByLayer",
452
                                                 "ByBlock",
453
                                                 "ForEmptyStyle" };
454
455
/* types of the 58 rest r2013+ properties.
456
 * 1:
457
 * 2:
458
 * 3:
459
 * 4:
460
 * 5:
461
 */
462
const unsigned char _dwg_VISUALSTYLE_proptypes[58] = {
463
  /* [0]  */ 2, 2, 2, 2,
464
  /* [4]  */ 3, 3, 4, 2,
465
  /* [8]  */ 2, 4, 4, 2,
466
  /* [12] */ 2, 3, 2, 4,
467
  /* [16] */ 3, 2, 2, 2,
468
  /* [20] */ 4, 2, 2, 2,
469
  /* [24] */ 1, 2, 3, 2,
470
  /* [28] */ 1, 1, 1, 1,
471
  /* [32] */ 1, 1, 1, 1,
472
  /* [36] */ 1, 2, 3, 3,
473
  /* [40] */ 2, 4, 2, 2,
474
  /* [44] */ 4, 1, 2, 2,
475
  /* [48] */ 2, 1, 2, 4,
476
  /* [52] */ 3, 2, 5, 1,
477
  /* [56] */ 3, 3
478
};
479
480
// returns the first ref from the handle vector.
481
BITCODE_H
482
shift_hv (BITCODE_H *hv, BITCODE_BL *num_p)
483
0
{
484
0
  BITCODE_H ref = hv[0];
485
0
  *num_p = *num_p - 1;
486
0
  memmove (&hv[0], &hv[1], *num_p * sizeof (BITCODE_H));
487
0
  return ref;
488
0
}
489
490
// delete an entry from an HV ("handle vector") at index i
491
void
492
delete_hv (BITCODE_H *entries, BITCODE_BS *num_p, BITCODE_BS i)
493
0
{
494
0
  BITCODE_H ref;
495
0
  BITCODE_BS nume = *num_p;
496
0
  assert (i < nume);
497
0
  ref = entries[i];
498
0
  *num_p = *num_p - 1;
499
0
  nume--;
500
0
  if (!ref->handleref.is_global)
501
0
    free (ref);
502
0
  if (!nume || i != nume) // not the last?
503
0
    {
504
0
      memmove (&entries[i], &entries[i + 1], (nume - i) * sizeof (BITCODE_H));
505
0
    }
506
0
}
507
508
// find if handle already exists, returns index or -1
509
BITCODE_BSd
510
find_hv (BITCODE_H *entries, BITCODE_BS num_entries, BITCODE_RLL handle_value)
511
802
{
512
802
  BITCODE_BS i;
513
#ifndef HAVE_NONNULL
514
  if (!entries || !num_entries)
515
    return -1; // empty handle vector
516
#else
517
802
  if (!num_entries)
518
0
    return -1; // empty handle vector
519
802
#endif
520
802
  for (i = 0; i < num_entries; i++)
521
802
    {
522
802
      if (entries[i] && (entries[i]->handleref.value == handle_value))
523
802
        return i;
524
802
    }
525
0
  return -1; // not found
526
802
}
527
528
/* from my dwg11.c, 1995 - rurban */
529
struct tm *
530
cvt_TIMEBLL (struct tm *tm, BITCODE_TIMEBLL date)
531
306
{
532
306
  double t, ss;
533
306
  long ja, jalpha, jb, jc, jd, je;
534
535
550
#define TRUNC(n) (long)floor (n)
536
537
306
  t = 0.864 * date.ms / 1000.0; /*t=1000000 = 1 day, means 86400 in seconds */
538
306
  if (date.days > 2299161)
539
85
    {
540
85
      jalpha = TRUNC (((date.days - 1867216) - 0.25) / 36524.25);
541
85
      ja = (long)(date.days + 1 + jalpha - TRUNC (0.25 * jalpha));
542
85
    }
543
221
  else
544
221
    ja = (long)date.days;
545
306
  if (ja < 1000)
546
211
    {
547
      // TDINDWG: relative minutes
548
211
      memset (tm, 0, sizeof (struct tm));
549
211
    }
550
95
  else
551
95
    {
552
95
      jb = ja + 1524;
553
95
      jc = TRUNC (6680.0 + ((jb - 2439870) - 122.1) / 365.25);
554
95
      jd = 365 * jc + TRUNC (0.25 * jc);
555
95
      je = TRUNC ((jb - jd) / 30.6001);
556
557
95
      tm->tm_mday = (int)(jb - jd - TRUNC (30.6001 * je));
558
95
      if (tm->tm_mday < 1)
559
0
        tm->tm_mday = 1;
560
95
      else if (tm->tm_mday > 31)
561
0
        tm->tm_mday %= 31;
562
95
      tm->tm_mon = (int)(je - 1);
563
95
      if (tm->tm_mon > 12)
564
8
        tm->tm_mon -= 12;
565
95
      tm->tm_year = (int)(jc - 4715);
566
95
      if (tm->tm_mon > 2)
567
87
        tm->tm_year--;
568
95
      if (tm->tm_year <= 0)
569
9
        tm->tm_year--;
570
95
      tm->tm_year -= 1900; // epoch start
571
95
      tm->tm_mon--;        // zero-based
572
95
    }
573
306
  tm->tm_hour = (int)floor (t / 3600.0);
574
306
  t -= tm->tm_hour * 3600.0;
575
306
  if (ja >= 1000)
576
95
    tm->tm_hour = tm->tm_hour % 24;
577
306
  tm->tm_min = (int)floor (t / 60.0);
578
306
  ss = t - (tm->tm_min * 60.0);
579
306
  tm->tm_sec = (int)ss;
580
  // sprintf (s, "%02d.%02d.%4d  %02d:%02d:%05.2f", d, m, y, hh, mm, ss);
581
306
  return tm;
582
306
}
583
584
/* in seconds */
585
long
586
tm_offset (void)
587
270
{
588
270
  time_t gmt, rawtime = time (NULL);
589
270
  struct tm *tm;
590
591
270
#ifdef HAVE_GMTIME_R
592
270
  struct tm gbuf;
593
270
  tm = gmtime_r (&rawtime, &gbuf);
594
#else
595
  tm = gmtime (&rawtime);
596
#endif
597
  // Force mktime() lookup dst in timezone database
598
270
  tm->tm_isdst = -1;
599
270
  gmt = mktime (tm);
600
270
  return (long)difftime (rawtime, gmt);
601
270
}
602
603
// portability compat funcs
604
605
EXPORT int
606
my_strcasecmp (const char *a, const char *b)
607
0
{
608
0
  while (*a && *b)
609
0
    {
610
0
      int diff = toupper ((unsigned char)*a) - toupper ((unsigned char)*b);
611
0
      if (diff)
612
0
        return diff;
613
0
      a++;
614
0
      b++;
615
0
    }
616
0
  return toupper ((unsigned char)*a) - toupper ((unsigned char)*b);
617
0
}
618
619
#ifdef _MSC_VER
620
EXPORT char *
621
basename (char *path)
622
{
623
  // I've looked at the winsdk basename implementation. It's a clusterfuck,
624
  // because they have 2-byte widechars. We only accept utf-8 paths
625
  char *p = strrchr (path, '/');
626
  if (!p)
627
    p = strrchr (path, '\\');
628
  return p;
629
}
630
#endif