1 //--- K.I.LIB ---
2 // kl_str.cpp : string classes for K.I.LIB
3
4 #include "stdafx.h"
5 #include "kilib.h"
6
7
8 //------------------------ 2byte文字処理用 ----------------------//
9
10
11 char kiStr::st_lb[256];
12
13 void kiStr::init()
14 {
15 st_lb[0] = 0;
16 for( int c=1; c!=256; c++ )
17 st_lb[c] = (::IsDBCSLeadByte(c) ? 2 : 1);
18 }
19
20
21 //-------------------------- コピー系色々 ------------------------//
22
23
24 kiStr::kiStr( int start_size )
25 {
26 (m_pBuf = new char[ m_ALen = start_size ])[0] = '\0';
27 }
28
29 kiStr::kiStr( const char* s, int min_size )
30 {
31 int slen = ki_strlen(s) + 1;
32 m_ALen = ( slen < min_size ) ? min_size : slen;
33 ki_memcpy( m_pBuf=new char[m_ALen], s, slen );
34 }
35
36 kiStr::kiStr( const kiStr& s )
37 {
38 ki_memcpy( m_pBuf=new char[m_ALen=s.m_ALen], s.m_pBuf, m_ALen=s.m_ALen );
39 }
40
41 kiStr& kiStr::operator = ( const kiStr& s )
42 {
43 if( this != &s )
44 *this = (const char*)s;
45 return *this;
46 }
47
48 kiStr& kiStr::operator = ( const char* s )
49 {
50 int slen = ki_strlen( s ) + 1;
51 int len = this->len();
52
53 if( m_ALen < slen || s <= m_pBuf+len || m_pBuf <= s+slen )
54 {
55 char* tmp = new char[ m_ALen = ( m_ALen>slen ? m_ALen : slen) ];
56 ki_memcpy( tmp, s, slen );
57 delete [] m_pBuf;
58 m_pBuf = tmp;
59 }
60 else
61 ki_memcpy( m_pBuf, s, slen );
62 return *this;
63 }
64
65 kiStr& kiStr::operator += ( const char* s )
66 {
67 int slen = ki_strlen( s ) + 1;
68 int len = this->len();
69
70 if( m_ALen < len+slen+1
71 || ( s <= m_pBuf && m_pBuf <= s+len )
72 || ( m_pBuf <= s && s <= m_pBuf+slen ) )
73 {
74 char* tmp = new char[ m_ALen = ( m_ALen>slen+len+1 ? m_ALen : slen+len+1) ];
75 ki_memcpy( tmp, m_pBuf, len );
76 delete [] m_pBuf;
77 m_pBuf = tmp;
78 }
79
80 ki_memcpy( m_pBuf+len, s, slen );
81 return *this;
82 }
83
84 kiStr& kiStr::operator += ( char c )
85 {
86 int len = this->len();
87
88 if( m_ALen < len+2 )
89 {
90 char* tmp = new char[ m_ALen=len+20 ];
91 ki_memcpy( tmp, m_pBuf, len );
92 delete [] m_pBuf;
93 m_pBuf = tmp;
94 }
95
96 m_pBuf[len]=c, m_pBuf[len+1]='\0';
97 return *this;
98 }
99
100 kiStr& kiStr::setInt( int n, bool cm )
101 {
102 if( n==0 )
103 m_pBuf[0] = '0', m_pBuf[1] = '\0';
104 else
105 {
106 bool minus = (n<0);
107 if( minus )
108 n= -n;
109
110 char tmp[30];
111 tmp[29]='\0';
112 int i;
113
114 for( i=28; i>=0; i-- )
115 {
116 if( cm && (29-i)%4==0 )
117 tmp[i--] = ',';
118 tmp[i] = '0' + n%10;
119 n /= 10;
120 if( n==0 )
121 break;
122 }
123
124 if( minus )
125 tmp[--i] = '-';
126
127 (*this) = tmp+i;
128 }
129 return (*this);
130 }
131
132 //-------------------------- 文字列処理全般 ------------------------//
133
134
135 kiStr::~kiStr()
136 {
137 delete [] m_pBuf;
138 }
139
140 kiStr::operator const char*() const
141 {
142 return m_pBuf;
143 }
144
145 bool kiStr::operator == ( const char* s ) const
146 {
147 return 0==ki_strcmp( m_pBuf, s );
148 }
149
150 bool kiStr::isSame( const char* s ) const
151 {
152 return 0==ki_strcmpi( m_pBuf, s );
153 }
154
155 int kiStr::len() const
156 {
157 return ki_strlen( m_pBuf );
158 }
159
160
161 //-------------------------- ユーティリティー ------------------------//
162
163
164 kiStr& kiStr::removeTrailWS()
165 {
166 char* m=m_pBuf-1;
167 for( char *p=m_pBuf; *p!='\0'; p=next(p) )
168 if( *p!=' ' && *p!='\t' && *p!='\n' )
169 m = p;
170 *next(m) = '\0';
171 return *this;
172 }
173
174 kiStr& kiStr::loadRsrc( UINT id )
175 {
176 ::LoadString( GetModuleHandle(NULL), id, m_pBuf, m_ALen );
177 return *this;
178 }
179
180 void kiPath::beSpecialPath( int nPATH )
181 {
182 switch( nPATH )
183 {
184 case Win: ::GetWindowsDirectory( m_pBuf, m_ALen ); break;
185 case Sys: ::GetSystemDirectory( m_pBuf, m_ALen ); break;
186 case Tmp: ::GetTempPath( m_ALen, m_pBuf ); break;
187 case Cur: ::GetCurrentDirectory( m_ALen, m_pBuf ); break;
188 case Exe_name:
189 ::GetModuleFileName( NULL, m_pBuf, m_ALen );break;
190 case Exe:
191 {
192 ::GetModuleFileName( NULL, m_pBuf, m_ALen );
193
194 char* m=NULL;
195 for( char *p=m_pBuf; *p!='\0'; p=next(p) )
196 if( *p=='\\' )
197 m = p;
198 if( m )
199 *m='\0';
200 break;
201 }
202 default:
203 {
204 *m_pBuf = '\0';
205
206 LPITEMIDLIST il;
207 if( NOERROR!=::SHGetSpecialFolderLocation( NULL, nPATH, &il ) )
208 return;
209 ::SHGetPathFromIDList( il, m_pBuf );
210 app()->shellFree( il );
211 }
212 }
213 }
214
215 void kiPath::beBackSlash( bool add )
216 {
217 char* last = m_pBuf;
218 for( char* p=m_pBuf; *p!='\0'; p=next(p) )
219 last=p;
220 if( *last=='\\' || *last=='/' )
221 {
222 if( !add )
223 *last = '\0';
224 }
225 else if( add && last!=m_pBuf )
226 *this += '\\';
227 }
228
229 bool kiPath::beDirOnly()
230 {
231 char* lastslash = m_pBuf-1;
232 for( char* p=m_pBuf; *p; p=next(p) )
233 if( *p=='\\' || *p=='/' )
234 lastslash = p;
235
236 *(lastslash+1) = '\0';
237
238 return (lastslash+1 != m_pBuf);
239 }
240
241 bool kiPath::isInSameDir(const char* q) const
242 {
243 bool diff=false;
244 for( const char *p=m_pBuf; *p && *q; p=next(p), q=next(q) )
245 if( *p != *q )
246 diff = true;
247 else if( diff && (*p=='\\' || *p=='/' || *q=='\\' || *q=='/') )
248 return false;
249
250 const char* r = (*p ? p : q);
251 if( *r )
252 for( ; *r; r=next(r) )
253 if( *r=='\\' || *r=='/' )
254 return false;
255 return true;
256 }
257
258 void kiPath::beShortPath()
259 {
260 ::GetShortPathName( m_pBuf, m_pBuf, m_ALen );
261 }
262
263 void kiPath::mkdir()
264 {
265 for( char *p=m_pBuf; *p; p=kiStr::next(p) )
266 {
267 if( (*p!='\\' && *p!='/') || (p-m_pBuf<=4) )
268 continue;
269 *p = '\0';
270 if( !kiSUtil::exist(m_pBuf) )
271 if( ::CreateDirectory( m_pBuf, NULL ) )
272 ::SHChangeNotify( SHCNE_MKDIR,SHCNF_PATH,(const void*)m_pBuf,NULL );
273 *p = '\\';
274 }
275 }
276
277 void kiPath::remove()
278 {
279 if( !kiSUtil::exist(*this) )
280 return;
281 if( !kiSUtil::isdir(*this) )
282 {
283 ::DeleteFile(*this);
284 return;
285 }
286
287 // buf == filename with no last '\\'
288 kiPath buf(*this);
289 buf.beBackSlash(false);
290
291 kiPath tmp(buf);
292 WIN32_FIND_DATA fd;
293 kiFindFile find;
294 find.begin( tmp += "\\*" );
295 while( find.next( &fd ) )
296 {
297 tmp = buf;
298 tmp += '\\';
299 tmp += fd.cFileName;
300 tmp.remove();
301 }
302 find.close();
303
304 ::RemoveDirectory( buf );
305 }
306
307 void kiPath::getBody( kiStr& str ) const
308 {
309 char *p=const_cast<char*>(name()),*x,c;
310 for( x=(*p=='.'?p+1:p); *x; x=next(x) ) // 先頭の.は拡張子と見なさない
311 if( *x=='.' )
312 break;
313 c=*x, *x='\0';
314 str=p;
315 *x=c;
316 }
317
318 void kiPath::getBody_all( kiStr& str ) const
319 {
320 // 最後の拡張子だけ削る版
321 char *p=const_cast<char*>(name()),*x=NULL, *n, c;
322 for( n=(*p=='.'?p+1:p); *n; n=next(n) ) // 先頭の.は拡張子と見なさない
323 if( *n=='.' )
324 x = n;
325 if( !x )x = n;
326
327 c =*x;
328 *x ='\0';
329 str=p;
330 *x =c;
331 }
332
333 const char* kiPath::ext( const char* str )
334 {
335 const char *ans = NULL, *p = name(str);
336 if( *p == '.' ) ++p; // 先頭の.は拡張子と見なさない
337 for( ; *p; p=next(p) )
338 if( *p=='.' )
339 ans = p;
340 return ans ? (ans+1) : p;
341 }
342
343 const char* kiPath::ext_all( const char* str )
344 {
345 const char* p = name(str);
346 if( *p == '.' ) ++p; // 先頭の.は拡張子と見なさない
347 for( ; *p; p=next(p) )
348 if( *p=='.' )
349 return (p+1);
350 return p;
351 }
352
353 const char* kiPath::name( const char* str )
354 {
355 const char* ans = str - 1;
356 for( const char* p=str; *p; p=next(p) )
357 if( *p=='\\' || *p=='/' )
358 ans = p;
359 return (ans+1);
360 }
361
362 UINT kiPath::getDriveType() const
363 {
364 char* p;
365 for( p=m_pBuf; *p=='\\'; p=next(p) );
366 for( p=m_pBuf; *p && *p!='\\'; p=next(p) );
367 char c=*(++p);*p='\0';
368 UINT ans=::GetDriveType( m_pBuf );
369 *p=c; return ans;
370 }
371
372 bool kiPath::endwithyen( const char* str )
373 {
374 for( const char *p=str,*last=str; *p; p=next(p) )
375 last=p;
376 return ( *last=='\\' || *last=='/' );
377 }
378