xref: /aosp_15_r20/external/lzma/CPP/Windows/PropVariantConv.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // PropVariantConv.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../Common/IntToString.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "Defs.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "PropVariantConv.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_TimeStringBufferSize = 64;
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker bool g_Timestamp_Show_UTC;
15*f6dc9357SAndroid Build Coastguard Worker #if 0
16*f6dc9357SAndroid Build Coastguard Worker bool g_Timestamp_Show_DisableZ;
17*f6dc9357SAndroid Build Coastguard Worker bool g_Timestamp_Show_TDelimeter;
18*f6dc9357SAndroid Build Coastguard Worker bool g_Timestamp_Show_ZoneOffset;
19*f6dc9357SAndroid Build Coastguard Worker #endif
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
ConvertUtcFileTimeToString2(const FILETIME & utc,unsigned ns100,char * s,int level,unsigned flags)22*f6dc9357SAndroid Build Coastguard Worker bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level, unsigned flags) throw()
23*f6dc9357SAndroid Build Coastguard Worker {
24*f6dc9357SAndroid Build Coastguard Worker   *s = 0;
25*f6dc9357SAndroid Build Coastguard Worker   FILETIME ft;
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker #if 0
28*f6dc9357SAndroid Build Coastguard Worker   Int64 bias64 = 0;
29*f6dc9357SAndroid Build Coastguard Worker #endif
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker   const bool show_utc =
32*f6dc9357SAndroid Build Coastguard Worker       (flags & kTimestampPrintFlags_Force_UTC) ? true :
33*f6dc9357SAndroid Build Coastguard Worker       (flags & kTimestampPrintFlags_Force_LOCAL) ? false :
34*f6dc9357SAndroid Build Coastguard Worker       g_Timestamp_Show_UTC;
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker   if (show_utc)
37*f6dc9357SAndroid Build Coastguard Worker     ft = utc;
38*f6dc9357SAndroid Build Coastguard Worker   else
39*f6dc9357SAndroid Build Coastguard Worker   {
40*f6dc9357SAndroid Build Coastguard Worker     if (!FileTimeToLocalFileTime(&utc, &ft))
41*f6dc9357SAndroid Build Coastguard Worker       return false;
42*f6dc9357SAndroid Build Coastguard Worker #if 0
43*f6dc9357SAndroid Build Coastguard Worker     if (g_Timestamp_Show_ZoneOffset)
44*f6dc9357SAndroid Build Coastguard Worker     {
45*f6dc9357SAndroid Build Coastguard Worker       const UInt64 utc64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;
46*f6dc9357SAndroid Build Coastguard Worker       const UInt64 loc64 = (((UInt64) ft.dwHighDateTime) << 32) +  ft.dwLowDateTime;
47*f6dc9357SAndroid Build Coastguard Worker       bias64 = (Int64)utc64 - (Int64)loc64;
48*f6dc9357SAndroid Build Coastguard Worker     }
49*f6dc9357SAndroid Build Coastguard Worker #endif
50*f6dc9357SAndroid Build Coastguard Worker   }
51*f6dc9357SAndroid Build Coastguard Worker 
52*f6dc9357SAndroid Build Coastguard Worker   SYSTEMTIME st;
53*f6dc9357SAndroid Build Coastguard Worker   if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
54*f6dc9357SAndroid Build Coastguard Worker   {
55*f6dc9357SAndroid Build Coastguard Worker     // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set.
56*f6dc9357SAndroid Build Coastguard Worker     return false;
57*f6dc9357SAndroid Build Coastguard Worker   }
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker   {
60*f6dc9357SAndroid Build Coastguard Worker     unsigned val = st.wYear;
61*f6dc9357SAndroid Build Coastguard Worker     if (val >= 10000)
62*f6dc9357SAndroid Build Coastguard Worker     {
63*f6dc9357SAndroid Build Coastguard Worker       *s++ = (char)('0' + val / 10000);
64*f6dc9357SAndroid Build Coastguard Worker       val %= 10000;
65*f6dc9357SAndroid Build Coastguard Worker     }
66*f6dc9357SAndroid Build Coastguard Worker     s[3] = (char)('0' + val % 10); val /= 10;
67*f6dc9357SAndroid Build Coastguard Worker     s[2] = (char)('0' + val % 10); val /= 10;
68*f6dc9357SAndroid Build Coastguard Worker     s[1] = (char)('0' + val % 10);
69*f6dc9357SAndroid Build Coastguard Worker     s[0] = (char)('0' + val / 10);
70*f6dc9357SAndroid Build Coastguard Worker     s += 4;
71*f6dc9357SAndroid Build Coastguard Worker   }
72*f6dc9357SAndroid Build Coastguard Worker   UINT_TO_STR_2('-', st.wMonth)
73*f6dc9357SAndroid Build Coastguard Worker   UINT_TO_STR_2('-', st.wDay)
74*f6dc9357SAndroid Build Coastguard Worker 
75*f6dc9357SAndroid Build Coastguard Worker   if (level > kTimestampPrintLevel_DAY)
76*f6dc9357SAndroid Build Coastguard Worker   {
77*f6dc9357SAndroid Build Coastguard Worker     const char setChar =
78*f6dc9357SAndroid Build Coastguard Worker #if 0
79*f6dc9357SAndroid Build Coastguard Worker       g_Timestamp_Show_TDelimeter ? 'T' : // ISO 8601
80*f6dc9357SAndroid Build Coastguard Worker #endif
81*f6dc9357SAndroid Build Coastguard Worker       ' ';
82*f6dc9357SAndroid Build Coastguard Worker     UINT_TO_STR_2(setChar, st.wHour)
83*f6dc9357SAndroid Build Coastguard Worker     UINT_TO_STR_2(':', st.wMinute)
84*f6dc9357SAndroid Build Coastguard Worker 
85*f6dc9357SAndroid Build Coastguard Worker     if (level >= kTimestampPrintLevel_SEC)
86*f6dc9357SAndroid Build Coastguard Worker     {
87*f6dc9357SAndroid Build Coastguard Worker       UINT_TO_STR_2(':', st.wSecond)
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker       if (level > kTimestampPrintLevel_SEC)
90*f6dc9357SAndroid Build Coastguard Worker       {
91*f6dc9357SAndroid Build Coastguard Worker         *s++ = '.';
92*f6dc9357SAndroid Build Coastguard Worker         /*
93*f6dc9357SAndroid Build Coastguard Worker         {
94*f6dc9357SAndroid Build Coastguard Worker           unsigned val = st.wMilliseconds;
95*f6dc9357SAndroid Build Coastguard Worker           s[2] = (char)('0' + val % 10); val /= 10;
96*f6dc9357SAndroid Build Coastguard Worker           s[1] = (char)('0' + val % 10);
97*f6dc9357SAndroid Build Coastguard Worker           s[0] = (char)('0' + val / 10);
98*f6dc9357SAndroid Build Coastguard Worker           s += 3;
99*f6dc9357SAndroid Build Coastguard Worker         }
100*f6dc9357SAndroid Build Coastguard Worker         *s++ = ' ';
101*f6dc9357SAndroid Build Coastguard Worker         */
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker         {
104*f6dc9357SAndroid Build Coastguard Worker           unsigned numDigits = 7;
105*f6dc9357SAndroid Build Coastguard Worker           UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000);
106*f6dc9357SAndroid Build Coastguard Worker           for (unsigned i = numDigits; i != 0;)
107*f6dc9357SAndroid Build Coastguard Worker           {
108*f6dc9357SAndroid Build Coastguard Worker             i--;
109*f6dc9357SAndroid Build Coastguard Worker             s[i] = (char)('0' + val % 10); val /= 10;
110*f6dc9357SAndroid Build Coastguard Worker           }
111*f6dc9357SAndroid Build Coastguard Worker           if (numDigits > (unsigned)level)
112*f6dc9357SAndroid Build Coastguard Worker             numDigits = (unsigned)level;
113*f6dc9357SAndroid Build Coastguard Worker           s += numDigits;
114*f6dc9357SAndroid Build Coastguard Worker         }
115*f6dc9357SAndroid Build Coastguard Worker         if (level >= kTimestampPrintLevel_NTFS + 1)
116*f6dc9357SAndroid Build Coastguard Worker         {
117*f6dc9357SAndroid Build Coastguard Worker           *s++ = (char)('0' + (ns100 / 10));
118*f6dc9357SAndroid Build Coastguard Worker           if (level >= kTimestampPrintLevel_NTFS + 2)
119*f6dc9357SAndroid Build Coastguard Worker             *s++ = (char)('0' + (ns100 % 10));
120*f6dc9357SAndroid Build Coastguard Worker         }
121*f6dc9357SAndroid Build Coastguard Worker       }
122*f6dc9357SAndroid Build Coastguard Worker     }
123*f6dc9357SAndroid Build Coastguard Worker   }
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker   if (show_utc)
126*f6dc9357SAndroid Build Coastguard Worker   {
127*f6dc9357SAndroid Build Coastguard Worker     if ((flags & kTimestampPrintFlags_DisableZ) == 0
128*f6dc9357SAndroid Build Coastguard Worker #if 0
129*f6dc9357SAndroid Build Coastguard Worker       && !g_Timestamp_Show_DisableZ
130*f6dc9357SAndroid Build Coastguard Worker #endif
131*f6dc9357SAndroid Build Coastguard Worker       )
132*f6dc9357SAndroid Build Coastguard Worker       *s++ = 'Z';
133*f6dc9357SAndroid Build Coastguard Worker   }
134*f6dc9357SAndroid Build Coastguard Worker #if 0
135*f6dc9357SAndroid Build Coastguard Worker   else if (g_Timestamp_Show_ZoneOffset)
136*f6dc9357SAndroid Build Coastguard Worker   {
137*f6dc9357SAndroid Build Coastguard Worker #if 1
138*f6dc9357SAndroid Build Coastguard Worker     {
139*f6dc9357SAndroid Build Coastguard Worker       char c;
140*f6dc9357SAndroid Build Coastguard Worker       if (bias64 < 0)
141*f6dc9357SAndroid Build Coastguard Worker       {
142*f6dc9357SAndroid Build Coastguard Worker         bias64 = -bias64;
143*f6dc9357SAndroid Build Coastguard Worker         c = '+';
144*f6dc9357SAndroid Build Coastguard Worker       }
145*f6dc9357SAndroid Build Coastguard Worker       else
146*f6dc9357SAndroid Build Coastguard Worker         c = '-';
147*f6dc9357SAndroid Build Coastguard Worker       UInt32 bias = (UInt32)((UInt64)bias64 / (10000000 * 60));
148*f6dc9357SAndroid Build Coastguard Worker #else
149*f6dc9357SAndroid Build Coastguard Worker     TIME_ZONE_INFORMATION zi;
150*f6dc9357SAndroid Build Coastguard Worker     const DWORD dw = GetTimeZoneInformation(&zi);
151*f6dc9357SAndroid Build Coastguard Worker     if (dw <= TIME_ZONE_ID_DAYLIGHT) // == 2
152*f6dc9357SAndroid Build Coastguard Worker     {
153*f6dc9357SAndroid Build Coastguard Worker       // UTC = LOCAL + Bias
154*f6dc9357SAndroid Build Coastguard Worker       Int32 bias = zi.Bias;
155*f6dc9357SAndroid Build Coastguard Worker       char c;
156*f6dc9357SAndroid Build Coastguard Worker       if (bias < 0)
157*f6dc9357SAndroid Build Coastguard Worker       {
158*f6dc9357SAndroid Build Coastguard Worker         bias = -bias;
159*f6dc9357SAndroid Build Coastguard Worker         c = '+';
160*f6dc9357SAndroid Build Coastguard Worker       }
161*f6dc9357SAndroid Build Coastguard Worker       else
162*f6dc9357SAndroid Build Coastguard Worker         c = '-';
163*f6dc9357SAndroid Build Coastguard Worker #endif
164*f6dc9357SAndroid Build Coastguard Worker       const UInt32 hours = (UInt32)bias / 60;
165*f6dc9357SAndroid Build Coastguard Worker       const UInt32 mins = (UInt32)bias % 60;
166*f6dc9357SAndroid Build Coastguard Worker       UINT_TO_STR_2(c, hours)
167*f6dc9357SAndroid Build Coastguard Worker       UINT_TO_STR_2(':', mins)
168*f6dc9357SAndroid Build Coastguard Worker     }
169*f6dc9357SAndroid Build Coastguard Worker   }
170*f6dc9357SAndroid Build Coastguard Worker #endif
171*f6dc9357SAndroid Build Coastguard Worker   *s = 0;
172*f6dc9357SAndroid Build Coastguard Worker   return true;
173*f6dc9357SAndroid Build Coastguard Worker }
174*f6dc9357SAndroid Build Coastguard Worker 
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
177*f6dc9357SAndroid Build Coastguard Worker {
178*f6dc9357SAndroid Build Coastguard Worker   return ConvertUtcFileTimeToString2(utc, 0, s, level);
179*f6dc9357SAndroid Build Coastguard Worker }
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw()
182*f6dc9357SAndroid Build Coastguard Worker {
183*f6dc9357SAndroid Build Coastguard Worker   char s[k_TimeStringBufferSize];
184*f6dc9357SAndroid Build Coastguard Worker   const bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level);
185*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0;; i++)
186*f6dc9357SAndroid Build Coastguard Worker   {
187*f6dc9357SAndroid Build Coastguard Worker     const Byte c = (Byte)s[i];
188*f6dc9357SAndroid Build Coastguard Worker     dest[i] = c;
189*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
190*f6dc9357SAndroid Build Coastguard Worker       break;
191*f6dc9357SAndroid Build Coastguard Worker   }
192*f6dc9357SAndroid Build Coastguard Worker   return res;
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker   char s[k_TimeStringBufferSize];
198*f6dc9357SAndroid Build Coastguard Worker   const bool res = ConvertUtcFileTimeToString(ft, s, level);
199*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0;; i++)
200*f6dc9357SAndroid Build Coastguard Worker   {
201*f6dc9357SAndroid Build Coastguard Worker     const Byte c = (Byte)s[i];
202*f6dc9357SAndroid Build Coastguard Worker     dest[i] = c;
203*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
204*f6dc9357SAndroid Build Coastguard Worker       break;
205*f6dc9357SAndroid Build Coastguard Worker   }
206*f6dc9357SAndroid Build Coastguard Worker   return res;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker 
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()
211*f6dc9357SAndroid Build Coastguard Worker {
212*f6dc9357SAndroid Build Coastguard Worker   *dest = 0;
213*f6dc9357SAndroid Build Coastguard Worker   switch (prop.vt)
214*f6dc9357SAndroid Build Coastguard Worker   {
215*f6dc9357SAndroid Build Coastguard Worker     case VT_EMPTY: return;
216*f6dc9357SAndroid Build Coastguard Worker     case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
217*f6dc9357SAndroid Build Coastguard Worker     case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
218*f6dc9357SAndroid Build Coastguard Worker     case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
219*f6dc9357SAndroid Build Coastguard Worker     case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
220*f6dc9357SAndroid Build Coastguard Worker     case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
221*f6dc9357SAndroid Build Coastguard Worker     case VT_FILETIME:
222*f6dc9357SAndroid Build Coastguard Worker     {
223*f6dc9357SAndroid Build Coastguard Worker       // const unsigned prec = prop.wReserved1;
224*f6dc9357SAndroid Build Coastguard Worker       int level = 0;
225*f6dc9357SAndroid Build Coastguard Worker       /*
226*f6dc9357SAndroid Build Coastguard Worker       if (prec == 0)
227*f6dc9357SAndroid Build Coastguard Worker         level = 7;
228*f6dc9357SAndroid Build Coastguard Worker       else if (prec > 16 && prec <= 16 + 9)
229*f6dc9357SAndroid Build Coastguard Worker         level = prec - 16;
230*f6dc9357SAndroid Build Coastguard Worker       */
231*f6dc9357SAndroid Build Coastguard Worker       ConvertUtcFileTimeToString(prop.filetime, dest, level);
232*f6dc9357SAndroid Build Coastguard Worker       return;
233*f6dc9357SAndroid Build Coastguard Worker     }
234*f6dc9357SAndroid Build Coastguard Worker     // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
235*f6dc9357SAndroid Build Coastguard Worker     case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
236*f6dc9357SAndroid Build Coastguard Worker     case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
237*f6dc9357SAndroid Build Coastguard Worker     case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
238*f6dc9357SAndroid Build Coastguard Worker     case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;
239*f6dc9357SAndroid Build Coastguard Worker     default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2);
240*f6dc9357SAndroid Build Coastguard Worker   }
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw()
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker   *dest = 0;
246*f6dc9357SAndroid Build Coastguard Worker   switch (prop.vt)
247*f6dc9357SAndroid Build Coastguard Worker   {
248*f6dc9357SAndroid Build Coastguard Worker     case VT_EMPTY: return;
249*f6dc9357SAndroid Build Coastguard Worker     case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;
250*f6dc9357SAndroid Build Coastguard Worker     case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;
251*f6dc9357SAndroid Build Coastguard Worker     case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
252*f6dc9357SAndroid Build Coastguard Worker     case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
253*f6dc9357SAndroid Build Coastguard Worker     case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
254*f6dc9357SAndroid Build Coastguard Worker     case VT_FILETIME:
255*f6dc9357SAndroid Build Coastguard Worker     {
256*f6dc9357SAndroid Build Coastguard Worker       // const unsigned prec = prop.wReserved1;
257*f6dc9357SAndroid Build Coastguard Worker       int level = 0;
258*f6dc9357SAndroid Build Coastguard Worker       /*
259*f6dc9357SAndroid Build Coastguard Worker       if (prec == 0)
260*f6dc9357SAndroid Build Coastguard Worker         level = 7;
261*f6dc9357SAndroid Build Coastguard Worker       else if (prec > 16 && prec <= 16 + 9)
262*f6dc9357SAndroid Build Coastguard Worker         level = prec - 16;
263*f6dc9357SAndroid Build Coastguard Worker       */
264*f6dc9357SAndroid Build Coastguard Worker       ConvertUtcFileTimeToString(prop.filetime, dest, level);
265*f6dc9357SAndroid Build Coastguard Worker       return;
266*f6dc9357SAndroid Build Coastguard Worker     }
267*f6dc9357SAndroid Build Coastguard Worker     // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
268*f6dc9357SAndroid Build Coastguard Worker     case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
269*f6dc9357SAndroid Build Coastguard Worker     case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
270*f6dc9357SAndroid Build Coastguard Worker     case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
271*f6dc9357SAndroid Build Coastguard Worker     case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;
272*f6dc9357SAndroid Build Coastguard Worker     default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);
273*f6dc9357SAndroid Build Coastguard Worker   }
274*f6dc9357SAndroid Build Coastguard Worker }
275