1/* 2 * buf.c -- 3 * 4 * Implementations of functions in the platform independent public Buf API. 5 * 6 * Copyright (c) 2000 by Andreas Kupries <a.kupries@westend.com> 7 * 8 * See the file "license.terms" for information on usage and redistribution 9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 10 * 11 * RCS: @(#) $Id: buf.c,v 1.1 2000/09/26 21:17:49 aku Exp $ 12 */ 13 14#include "buf.h" 15 16/* 17 * Codestring used to associate the 18 * initialization flag with an interpreter. 19 */ 20 21#define ASSOC "memchan:buf" 22 23/* Internal declaration of buffers. 24 */ 25 26typedef struct Buffer_ { 27 Buf_BufferType* type; /* Reference to the type of the buffer */ 28 ClientData clientData; /* The information pertinent to the used type. */ 29 int refCount; /* Number of references hold by other parts 30 * of the application to this buffer. Initialized 31 * to 0 by the creator procedures implemented here. 32 */ 33} Buffer; 34 35/* Internal declaration of a buffer position. 36 */ 37 38typedef struct BufferPosition_ { 39 Buf_Buffer buf; /* The buffer this position belongs to */ 40 int offset; /* The offset into the data area */ 41} BufferPosition; 42 43/* 44 *------------------------------------------------------* 45 * 46 * Buf_IsInitialized -- 47 * 48 * Check wether the buffer system is initialized for 49 * the specified interpreter 50 * 51 * Sideeffects: 52 * None. 53 * 54 * Result: 55 * A boolean value. 0 indicates no 56 * initialization, 1 the opposite. 57 * 58 *------------------------------------------------------* 59 */ 60 61int 62Buf_IsInitialized (interp) 63 Tcl_Interp* interp; 64{ 65 Tcl_InterpDeleteProc* proc = (Tcl_InterpDeleteProc*) NULL; 66 return (int) Tcl_GetAssocData (interp, ASSOC, &proc); 67} 68 69/* 70 *------------------------------------------------------* 71 * 72 * Buf_Init -- 73 * 74 * Initializes the buffer system in the specified 75 * interpreter. 76 * 77 * Sideeffects: 78 * Associates data with the specified 79 * interpreter to remember the initialization 80 * 81 * Result: 82 * A standard TCL error code. 83 * 84 *------------------------------------------------------* 85 */ 86 87 88int 89Buf_Init (interp) 90 Tcl_Interp* interp; 91{ 92 /* There is nothing to initialize here. But we have an operation 93 * querying the state of initialization, so we have to remember 94 * at least this. 95 */ 96 97 if (Buf_IsInitialized (interp)) { 98 /* catch multiple initialization of an interpreter 99 */ 100 return TCL_OK; 101 } 102 103 Tcl_SetAssocData (interp, ASSOC, 104 (Tcl_InterpDeleteProc*) NULL, 105 (ClientData) 1); 106 107 return TCL_OK; 108} 109 110/* 111 *------------------------------------------------------* 112 * 113 * Buf_RegisterType -- 114 * 115 * Registers a new buffer type. 116 * 117 * Sideeffects: 118 * None. 119 * 120 * Result: 121 * None. 122 * 123 *------------------------------------------------------* 124 */ 125 126void 127Buf_RegisterType (bufType) 128 Buf_BufferType* bufType; 129{ 130 /* There are currently no operations in the interface which require 131 * an internal list of registered buffer types, etc. So this function 132 * can and will be a no-op for now. 133 */ 134} 135 136/* 137 *------------------------------------------------------* 138 * 139 * Buf_IncrRefcount -- 140 * 141 * Tells the specified buffer that a new reference 142 * to it is hold by someone else. 143 * 144 * Sideeffects: 145 * See above. 146 * 147 * Result: 148 * None. 149 * 150 *------------------------------------------------------* 151 */ 152 153void 154Buf_IncrRefcount (buf) 155 Buf_Buffer buf; 156{ 157 ((Buffer*) buf)->refCount ++; 158} 159 160/* 161 *------------------------------------------------------* 162 * 163 * Buf_DecrRefcount -- 164 * 165 * Tells the specified buffer that a reference to it 166 * is no longer in existence. 167 * 168 * Sideeffects: 169 * Deletes the buffer if the last reference 170 * to it is released. 171 * 172 * Result: 173 * None. 174 * 175 *------------------------------------------------------* 176 */ 177 178void 179Buf_DecrRefcount (buf) 180 Buf_Buffer buf; 181{ 182 Buffer* iBuf = (Buffer*) buf; 183 184 iBuf->refCount --; 185 186 if (iBuf->refCount <= 0) { 187 /* No references are hold by anyone else anymore. 188 * So remove the buffer, we won't need it again. 189 */ 190 191 iBuf->type->freeProc (buf, iBuf->clientData); 192 Tcl_Free ((char*) iBuf); 193 } 194} 195 196/* 197 *------------------------------------------------------* 198 * 199 * Buf_IsShared -- 200 * 201 * Checks wether the buffer is shared among 202 * different parts of the application. 203 * 204 * Sideeffects: 205 * None. 206 * 207 * Result: 208 * A boolean value. 1 indicates a shared 209 * buffer, 0 the opposite. 210 * 211 *------------------------------------------------------* 212 */ 213 214int 215Buf_IsShared (buf) 216 Buf_Buffer buf; 217{ 218 return (((Buffer*) buf)->refCount > 1); 219} 220 221/* 222 *------------------------------------------------------* 223 * 224 * Buf_GetType -- 225 * 226 * Retrieves the type structure of a buffer. 227 * 228 * Sideeffects: 229 * None. 230 * 231 * Result: 232 * A reference to the type of the buffer. 233 * 234 *------------------------------------------------------* 235 */ 236 237Buf_BufferType* 238Buf_GetType (buf) 239 Buf_Buffer buf; 240{ 241 return ((Buffer*) buf)->type; 242} 243 244/* 245 *------------------------------------------------------* 246 * 247 * Buf_GetTypeName -- 248 * 249 * Retrieves the name of the type of a buffer. 250 * 251 * Sideeffects: 252 * None. 253 * 254 * Result: 255 * A reference to the string containing the 256 * name of the type of the buffer. 257 * 258 *------------------------------------------------------* 259 */ 260 261CONST char* 262Buf_GetTypeName (buf) 263 Buf_Buffer buf; 264{ 265 return ((Buffer*) buf)->type->typeName; 266} 267 268/* 269 *------------------------------------------------------* 270 * 271 * Buf_Size -- 272 * 273 * Returns the number of bytes currently stored in 274 * the buffer. 275 * 276 * Sideeffects: 277 * None. 278 * 279 * Result: 280 * See above. 281 * 282 *------------------------------------------------------* 283 */ 284 285int 286Buf_Size (buf) 287 Buf_Buffer buf; 288{ 289 Buffer* iBuf = (Buffer*) buf; 290 return iBuf->type->sizeProc (buf, iBuf->clientData); 291} 292 293/* 294 *------------------------------------------------------* 295 * 296 * Buf_GetClientData -- 297 * 298 * Retrieves the type specific client information 299 * of a buffer. 300 * 301 * Sideeffects: 302 * None. 303 * 304 * Result: 305 * The client information of the buffer. 306 * 307 *------------------------------------------------------* 308 */ 309 310ClientData 311Buf_GetClientData (buf) 312 Buf_Buffer buf; 313{ 314 return ((Buffer*) buf)->clientData; 315} 316 317/* 318 *------------------------------------------------------* 319 * 320 * Buf_Create -- 321 * 322 * Create a new buffer (refcount 0) from its type 323 * and the asssociated type specific information 324 * 325 * Sideeffects: 326 * Allocates memory. 327 * 328 * Result: 329 * A new buffer token. 330 * 331 *------------------------------------------------------* 332 */ 333 334 335Buf_Buffer 336Buf_Create (bufType, clientData) 337 Buf_BufferType* bufType; 338 ClientData clientData; 339{ 340 Buffer* iBuf = (Buffer*) Tcl_Alloc (sizeof (Buffer)); 341 342 iBuf->type = bufType; 343 iBuf->clientData = clientData; 344 iBuf->refCount = 0; 345 346 return (Buf_Buffer) iBuf; 347} 348 349/* 350 *------------------------------------------------------* 351 * 352 * Buf_Dup -- 353 * 354 * Duplicates a buffer and its contents. 355 * 356 * Sideeffects: 357 * As of the used buffer driver. 358 * 359 * Result: 360 * A new buffer token. 361 * 362 *------------------------------------------------------* 363 */ 364 365Buf_Buffer 366Buf_Dup (buf) 367 Buf_Buffer buf; 368{ 369 Buffer* iBuf = (Buffer*) buf; 370 return iBuf->type->dupProc (buf, iBuf->clientData); 371} 372 373/* 374 *------------------------------------------------------* 375 * 376 * Buf_Read -- 377 * 378 * Reads at most size bytes from the current location 379 * in the buffer and stores it into outbuf. 380 * 381 * Sideeffects: 382 * Moves the read pointer behind the bytes 383 * just read from the buffer. 384 * 385 * Result: 386 * The number of bytes actually read from 387 * the buffer. 388 * 389 *------------------------------------------------------* 390 */ 391 392int 393Buf_Read (buf, outbuf, size) 394 Buf_Buffer buf; 395 VOID* outbuf; 396 int size; 397{ 398 Buffer* iBuf = (Buffer*) buf; 399 return iBuf->type->readProc (buf, iBuf->clientData, outbuf, size); 400} 401 402/* 403 *------------------------------------------------------* 404 * 405 * Buf_Write -- 406 * 407 * Writes at most size bytes from inbuf and appends 408 * it the buffer 409 * 410 * Sideeffects: 411 * Moves the write pointer behind the bytes 412 * just written into the buffer. 413 * 414 * Result: 415 * The number of bytes actually written 416 * into the buffer. 417 * 418 *------------------------------------------------------* 419 */ 420 421int 422Buf_Write (buf, inbuf, size) 423 Buf_Buffer buf; 424 CONST VOID* inbuf; 425 int size; 426{ 427 Buffer* iBuf = (Buffer*) buf; 428 429 if (iBuf->type->writeProc == NULL) { 430 return 0; 431 } else { 432 return iBuf->type->writeProc (buf, iBuf->clientData, inbuf, size); 433 } 434} 435 436/* 437 *------------------------------------------------------* 438 * 439 * Buf_PositionPtr -- 440 * 441 * Converts the logical location in the buffer into 442 * a reference to the data area. 443 * 444 * Sideeffects: 445 * None. 446 * 447 * Result: 448 * A character pointer 449 * 450 *------------------------------------------------------* 451 */ 452 453char* 454Buf_PositionPtr (loc) 455 Buf_BufferPosition loc; 456{ 457 BufferPosition* bPos = (BufferPosition*) loc; 458 Buffer* iBuf = (Buffer*) bPos->buf; 459 char* data = iBuf->type->dataProc (bPos->buf, iBuf->clientData); 460 461 return data + bPos->offset; 462} 463 464/* 465 *------------------------------------------------------* 466 * 467 * Buf_PositionOffset -- 468 * 469 * Converts the logical location in the buffer into 470 * an offset relative to the start of the data area 471 * of the underlying buffer. 472 * 473 * Sideeffects: 474 * None. 475 * 476 * Result: 477 * An integer value. 478 * 479 *------------------------------------------------------* 480 */ 481 482int 483Buf_PositionOffset (loc) 484 Buf_BufferPosition loc; 485{ 486 BufferPosition* bPos = (BufferPosition*) loc; 487 return bPos->offset; 488} 489 490/* 491 *------------------------------------------------------* 492 * 493 * Buf_Tell -- 494 * 495 * Creates a logical position in the buffer pointing 496 * to the current location of the read pointer. 497 * 498 * Sideeffects: 499 * Allocates memory, adds a reference to 500 * the buffer. 501 * 502 * Result: 503 * A buffer position. 504 * 505 *------------------------------------------------------* 506 */ 507 508Buf_BufferPosition 509Buf_Tell (buf) 510 Buf_Buffer buf; 511{ 512 Buffer* iBuf = (Buffer*) buf; 513 BufferPosition* bPos = (BufferPosition*) Tcl_Alloc (sizeof (BufferPosition)); 514 515 bPos->buf = buf; 516 bPos->offset = iBuf->type->tellProc (buf, iBuf->clientData); 517 518 /* 519 * The position holds a reference to the buffer, remember that. 520 */ 521 522 Buf_IncrRefcount (buf); 523 524 return (Buf_BufferPosition) bPos; 525} 526 527/* 528 *------------------------------------------------------* 529 * 530 * Buf_FreePosition -- 531 * 532 * Deletes a logical position in a buffer. 533 * 534 * Sideeffects: 535 * Deallocates memory, removes a reference to 536 * the buffer, may free the referenced buffer. 537 * 538 * Result: 539 * None. 540 * 541 *------------------------------------------------------* 542 */ 543 544void 545Buf_FreePosition (loc) 546 Buf_BufferPosition loc; 547{ 548 BufferPosition* bPos = (BufferPosition*) loc; 549 550 Buf_DecrRefcount (bPos->buf); 551 Tcl_Free ((char*) bPos); 552} 553 554/* 555 *------------------------------------------------------* 556 * 557 * Buf_MovePosition -- 558 * 559 * Move a logical position in a buffer. 560 * 561 * Sideeffects: 562 * See above. 563 * 564 * Result: 565 * None. 566 * 567 *------------------------------------------------------* 568 */ 569 570void 571Buf_MovePosition (loc, offset) 572 Buf_BufferPosition loc; 573 int offset; 574{ 575 BufferPosition* bPos = (BufferPosition*) loc; 576 577 if ((bPos->offset + offset) < 0) { 578 Tcl_Panic ("Moved buffer location out of range"); 579 } 580 581 bPos->offset += offset; 582} 583 584/* 585 *------------------------------------------------------* 586 * 587 * Buf_DupPosition -- 588 * 589 * Duplicates a logical position in a buffer. 590 * 591 * Sideeffects: 592 * Allocates memory, adds another reference 593 * to the underlying buffer. 594 * 595 * Result: 596 * A token for the new buffer position. 597 * 598 *------------------------------------------------------* 599 */ 600 601Buf_BufferPosition 602Buf_DupPosition (loc) 603 Buf_BufferPosition loc; 604{ 605 BufferPosition* bPos = (BufferPosition*) loc; 606 BufferPosition* newPos = (BufferPosition*) Tcl_Alloc (sizeof (BufferPosition)); 607 608 newPos->buf = bPos->buf; 609 newPos->offset = bPos->offset; 610 611 Buf_IncrRefcount (bPos->buf); 612 613 return (Buf_BufferPosition) newPos; 614} 615 616/* 617 *------------------------------------------------------* 618 * 619 * Buf_PositionFromOffset -- 620 * 621 * Creates a logical position from an offset into 622 * the data area and a buffer. 623 * 624 * Sideeffects: 625 * Allocates memory, adds another reference 626 * to the buffer. 627 * 628 * Result: 629 * A token for the new buffer position. 630 * 631 *------------------------------------------------------* 632 */ 633 634Buf_BufferPosition 635Buf_PositionFromOffset (buf, offset) 636 Buf_Buffer buf; 637 int offset; 638{ 639 BufferPosition* newPos = (BufferPosition*) Tcl_Alloc (sizeof (BufferPosition)); 640 641 newPos->buf = buf; 642 newPos->offset = offset; 643 644 Buf_IncrRefcount (buf); 645 646 return (Buf_BufferPosition) newPos; 647} 648