61 c_held_string((char * const *)c_character_manager.internal_offset_mem())
65 : c_character_manager(strlen(initial.observe()) + 1, (
abyte *)initial.observe()),
66 c_held_string((char * const *)c_character_manager.internal_offset_mem())
72 if (!initial) initial =
' ';
73 int new_size = c_character_manager.
length() - 1;
78 memset((
void *)c_character_manager.
access(), (
int)initial, (
size_t)new_size);
79 c_character_manager.
put(new_size,
'\0');
85 c_character_manager(s1.c_character_manager),
86 c_held_string((char * const *)c_character_manager.internal_offset_mem())
93 c_character_manager.
put(0,
'\0');
101 c_held_string((char * const *)c_character_manager.internal_offset_mem())
103 if (!initial)
return;
110 va_start(args, initial);
114 int length = va_arg(args,
int);
116 c_character_manager +=
abyte(0);
141 {
return (
const char *)c_character_manager.
observe(); }
152 if (!s2_cast)
throw "error: astring::<: unknown type";
160 {
return strcmp(
observe(), that) == 0; }
163 {
return (
find(to_find, 0) < 0) ? false :
true; }
171 c_character_manager.
swap_contents(copy_of_this.c_character_manager);
177 va_start(args, initial);
186 printf(
"base_sprintf entry, format string is: %s\n", initial);
189 if (!initial)
return *
this;
190 if (!initial[0])
return *
this;
193 char flag_chars[23], width_chars[23], precision_chars[23], modifier_chars[23];
196 for (
const char *traverser = initial; *traverser; traverser++) {
198 printf(
"index=%d, char=%c\n",
int(traverser - initial), *traverser);
201 if (*traverser !=
'%') {
208 printf(
"index=%d, char=%c\n",
int(traverser - initial), *traverser);
210 if (*traverser ==
'%') {
215 bool failure =
false;
218 seek_flag(traverser, flag_chars, failure);
224 seek_width(traverser, width_chars);
225 seek_precision(traverser, precision_chars);
226 seek_modifier(traverser, modifier_chars);
227 get_type_character(traverser, args, *
this, flag_chars,
228 width_chars, precision_chars, modifier_chars);
233 void astring::seek_flag(
const char *&traverser,
char *flag_chars,
bool &failure)
235 flag_chars[0] =
'\0';
237 bool keep_going =
true;
238 while (!failure && keep_going) {
239 switch (*traverser) {
240 case '-':
case '+':
case ' ':
case '\011':
case '#':
241 flag_chars[strlen(flag_chars) + 1] =
'\0';
242 flag_chars[strlen(flag_chars)] = *traverser++;
251 if (strlen(flag_chars)) printf(
"[flag=%s]\n", flag_chars);
252 else printf(
"no flags\n");
256 void astring::seek_width(
const char *&traverser,
char *width_chars)
258 width_chars[0] =
'\0';
259 bool no_more_nums =
false;
260 bool first_num =
true;
261 while (!no_more_nums) {
262 char wideness[2] = { *traverser,
'\0' };
263 if (first_num && (wideness[0] ==
'0')) {
264 strcpy(width_chars, wideness);
266 }
else if (first_num && (wideness[0] ==
'*') ) {
267 strcpy(width_chars, wideness);
270 }
else if ( (wideness[0] <=
'9') && (wideness[0] >=
'0') ) {
272 strcat(width_chars, wideness);
274 }
else no_more_nums =
true;
278 if (strlen(width_chars)) printf(
"[width=%s]\n", width_chars);
279 else printf(
"no widths\n");
283 void astring::seek_precision(
const char *&traverser,
char *precision_chars)
285 precision_chars[0] =
'\0';
286 if (*traverser !=
'.')
return;
287 strcpy(precision_chars,
".");
289 bool no_more_nums =
false;
290 bool first_num =
true;
291 while (!no_more_nums) {
292 char preciseness[2] = { *traverser,
'\0' };
293 if (first_num && (preciseness[0] ==
'0')) {
294 strcat(precision_chars, preciseness);
297 }
else if (first_num && (preciseness[0] ==
'*') ) {
298 strcat(precision_chars, preciseness);
301 }
else if ( (preciseness[0] <=
'9') && (preciseness[0] >=
'0') ) {
302 strcat(precision_chars, preciseness);
304 }
else no_more_nums =
true;
308 if (strlen(precision_chars)) printf(
"[precis=%s]\n", precision_chars);
309 else printf(
"no precision\n");
313 void astring::seek_modifier(
const char *&traverser,
char *modifier_chars)
315 modifier_chars[0] =
'\0';
316 switch (*traverser) {
317 case 'F':
case 'N':
case 'h':
case 'l':
case 'L': {
318 modifier_chars[strlen(modifier_chars) + 1] =
'\0';
319 modifier_chars[strlen(modifier_chars)] = *traverser++;
324 if (strlen(modifier_chars)) printf(
"[mod=%s]\n", modifier_chars);
325 else printf(
"no modifiers\n");
329 void astring::get_type_character(
const char * &traverser, va_list &args,
330 astring &output_string,
const char *flag_chars,
const char *width_chars,
331 const char *precision_chars,
const char *modifier_chars)
333 char formatting[120];
334 strcpy(formatting,
"%");
335 strcat(formatting, flag_chars);
336 strcat(formatting, width_chars);
337 strcat(formatting, precision_chars);
338 strcat(formatting, modifier_chars);
339 char tmposh[2] = { *traverser,
'\0' };
340 strcat(formatting, tmposh);
342 printf(
"format: %s\n", formatting);
345 enum argument_size { bits_8, bits_16, bits_32, bits_64, bits_80 };
346 bool ints_are_32_bits;
348 ints_are_32_bits =
true;
349 #elif defined(__OS2__)
350 ints_are_32_bits =
true;
351 #elif defined(__MSDOS__)
352 ints_are_32_bits =
false;
353 #elif defined(__WIN32__)
354 ints_are_32_bits =
false;
356 ints_are_32_bits =
true;
358 argument_size next_argument;
359 bool use_dynamic_sprintf =
false;
361 switch (*traverser) {
362 case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
363 next_argument = bits_16;
364 if (ints_are_32_bits) next_argument = bits_32;
366 case 'f':
case 'e':
case 'g':
case 'E':
case 'G':
367 next_argument = bits_64;
370 next_argument = bits_8;
373 next_argument = bits_32;
374 use_dynamic_sprintf =
true;
377 next_argument = bits_32;
380 next_argument = bits_32;
386 printf(
"failure in type char: %c\n", *traverser);
388 output_string += formatting;
397 if (strlen(modifier_chars)) {
398 switch (modifier_chars[0]) {
400 next_argument = bits_16;
401 if (ints_are_32_bits) next_argument = bits_32;
404 next_argument = bits_32;
407 next_argument = bits_16;
410 next_argument = bits_32;
413 next_argument = bits_80;
419 printf(
"failure in modifier: %s\n", modifier_chars);
421 output_string += formatting;
428 switch (next_argument) {
431 case bits_8:
case bits_16:
432 if (ints_are_32_bits)
::sprintf(
temp, formatting, va_arg(args,
long));
433 else ::sprintf(
temp, formatting, va_arg(args,
int));
436 if (use_dynamic_sprintf) {
438 char *to_print = va_arg(args,
char *);
442 use_dynamic_sprintf =
false;
447 use_dynamic_sprintf =
false;
454 } else ::sprintf(
temp, formatting, va_arg(args,
void *));
463 if (use_dynamic_sprintf) {
464 output_string += temp2;
466 }
else output_string +=
temp;
473 if (!initial)
return;
480 va_start(args, initial);
484 int length = va_arg(args,
int);
486 c_character_manager +=
abyte(0);
498 if (
length() >= len)
return;
500 memset(
pad.access(), padding,
pad.length());
506 if (
length() <= len)
return;
513 c_character_manager = s1.c_character_manager;
528 c_character_manager.
zap(position1, position2);
533 for (
int i = 0; i <
length(); i++)
534 if ( (
get(i) >=
'A') && (
get(i) <=
'Z') )
540 for (
int i = 0; i <
length(); i++)
541 if ( (
get(i) >=
'a') && (
get(i) <=
'z') )
561 if (!array_to_stuff)
return;
562 array_to_stuff[0] =
'\0';
563 if ( (how_many <= 0) || (
length() <= 0) )
return;
572 {
return strcasecmp(
observe(), that) == 0; }
575 {
return char_find(to_find, position, reverse,
false); }
578 {
return char_find(to_find, position, reverse,
true); }
581 {
return char_find_any(to_find, position, reverse,
true); }
584 {
return char_find_any(to_find, position, reverse,
false); }
588 {
return char_find_any(to_find, position, reverse,
false,
true); }
592 if ( (input <=
'Z') && (input >=
'A') )
return input -
CASE_DIFFERENCE;
596 int astring::char_find(
char to_find,
int position,
bool reverse,
597 bool case_sense)
const
599 if (position < 0)
return common::OUT_OF_RANGE;
600 if (position >
end())
return common::OUT_OF_RANGE;
602 for (
int i = position; i >= 0; i--) {
603 if (case_sense && (
get(i) == to_find))
return i;
608 const char *
const pos = strchr(
observe() + position, to_find);
609 if (pos)
return int(pos -
observe());
611 for (
int i = position; i <
length(); i++)
615 return common::NOT_FOUND;
620 for (
int i = 0; i < list.
length(); i++)
627 for (
int i = 0; i < list.
length(); i++)
628 if (to_check == list[i])
return true;
634 bool saw_match =
false;
635 for (
int i = 0; i < list.
length(); i++)
636 if (to_check == list[i]) {
643 int astring::char_find_any(
const astring &to_find,
int position,
bool reverse,
644 bool case_sense,
bool invert_find)
const
646 if (position < 0)
return common::OUT_OF_RANGE;
647 if (position >
end())
return common::OUT_OF_RANGE;
649 for (
int i = position; i >= 0; i--) {
660 for (
int i = position; i <
length(); i++) {
671 return common::NOT_FOUND;
675 {
return str_find(to_find, posn, reverse,
true); }
678 {
return str_find(to_find, posn, reverse,
false); }
680 int astring::str_find(
const astring &to_find,
int posn,
bool reverse,
681 bool case_sense)
const
684 if (!to_find.
length())
return common::BAD_INPUT;
689 posn =
find(to_find[0], posn, reverse);
690 else posn =
ifind(to_find[0], posn, reverse);
691 if (posn < 0)
return common::NOT_FOUND;
700 for (
int i = posn; i >= 0; i--)
705 const int find_len = to_find.
length();
706 const int str_len =
length();
707 const char first_char = to_find[0];
708 bounds_return(posn, 0, str_len - find_len, common::OUT_OF_RANGE);
709 for (
int i = posn - 1;
710 ( ( (i =
find(first_char, i + 1)) >= 0)
722 for (
int i = posn; i >= 0; i--)
727 for (
int i = posn; i <
length() - to_find.
length() + 1; i++)
732 return common::NOT_FOUND;
744 if (position < 0) position = 0;
745 if (position >
end()) position = 0;
746 abyte &found = c_character_manager.
use(position);
747 char &to_return = *((
char *)(&found));
753 if (position < 0) position = 0;
754 if (position >
end()) position = 0;
755 const abyte &found = c_character_manager.
get(position);
756 const char &to_return = *((
const char *)(&found));
762 if (!
length())
return default_value;
764 int fields = sscanf(
observe(),
"%d", &to_return);
765 if (fields < 1)
return default_value;
771 if (!
length())
return default_value;
773 int fields = sscanf(
observe(),
"%ld", &to_return);
774 if (fields < 1)
return default_value;
780 if (!
length())
return default_value;
782 int fields = sscanf(
observe(),
"%f", &to_return);
783 if (fields < 1)
return default_value;
789 if (!
length())
return default_value;
791 int fields = sscanf(
observe(),
"%lf", &to_return);
792 if (fields < 1)
return default_value;
798 if (!s1)
return *
this;
800 c_character_manager.
insert(len,
int(strlen(s1)));
801 memmove((
char *)&c_character_manager[len], s1,
int(strlen(s1)));
808 c_character_manager.
insert(len, 1);
809 c_character_manager.
put(len, s1);
814 int start_second,
int count,
bool case_sensitive)
const
821 if (!case_sensitive) {
822 return !strncasecmp(&
observe()[start_first],
823 &to_compare.
observe()[start_second], count);
825 return !memcmp((
void *)&
observe()[start_first],
826 (
void *)&to_compare.
observe()[start_second], count);
871 if (bender < start)
return false;
872 const int last =
end();
887 {
return substring(start, start + count - 1); }
898 if (
this == &to_insert) {
900 insert(position, copy_of_me);
902 c_character_manager.
insert(position, to_insert.
length());
903 c_character_manager.
overwrite(position, to_insert.c_character_manager,
910 int where =
find(tag);
912 zap(where, where + tag.
end());
913 insert(where, replacement);
919 bool did_any =
false;
920 for (
int i = 0; i <
length(); i++) {
921 int indy =
find(to_replace, i);
926 i += new_string.
length() - 1;
934 bool did_any =
false;
935 for (
int i = 0; i <
length(); i++) {
936 if (
get(i) == to_replace) {
946 for (
int i = 0; i < match_list.
length(); i++)
947 if (to_match == match_list.
get(i))
return true;
968 {
return detach(source, *
this); }
1009 if (!initial)
return;
1011 va_start(args, initial);
1020 const int len = int(strlen(to_attach));
1021 const int old_pos = packed_form.
last();
1022 packed_form.
insert(old_pos + 1, len + 1);
1023 memmove((
char *)packed_form.
observe() + old_pos + 1, to_attach, len + 1);
1028 if (!packed_form.
length())
return false;
1030 const void *zero_posn = memchr(packed_form.
observe(),
'\0',
1040 to_detach = (
char *)packed_form.
observe();
1043 int find_len = int((
abyte *)zero_posn - packed_form.
observe());
1045 packed_form.
zap(0, find_len);
1056 if (cast) *
this += *cast;
1057 else *
this +=
astring(
s.observe());
1070 if (cast) *
this = *cast;
1084 if (!cast)
throw "error: astring::sub_string: unknown type";
1089 int start_second,
int count,
bool case_sensitive)
const
1091 const astring *cast =
dynamic_cast<const astring *
>(&to_compare);
1092 if (cast)
return compare(*cast, start_first, start_second, count, case_sensitive);
1094 count, case_sensitive);
1100 if (cast) this->
insert(position, *cast);
outcome put(int index, const contents &to_put)
Stores an object at the index "index" in the array.
outcome insert(int index, int new_indices)
Adds "new_indices" new positions for objects into the array at "index".
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
const contents * observe() const
Returns a pointer to the underlying C array of data.
outcome overwrite(int index, const array &write_with, int count=-1)
Stores the array "write_with" into the current array at the "index".
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
contents * access()
A non-constant access of the underlying C-array. BE REALLY CAREFUL.
contents *const * internal_offset_mem() const
Gritty Internal: the start of the actual stored data.
int length() const
Returns the current reported length of the allocated C array.
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
void swap_contents(array< contents > &other)
Exchanges the contents of "this" and "other".
contents & use(int index)
A non-constant version of get(); the returned object can be modified.
int last() const
Returns the last valid element in the array.
Provides a dynamically resizable ASCII character string.
virtual ~astring()
destroys any storage for the string.
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
astring & operator=(const astring &s)
Sets the contents of this string to "s".
astring lower() const
like to_lower(), but returns a new string rather than modifying this.
astring middle(int start, int count)
returns the middle of the string from "start" with "count" characters.
static bool matches(const astring &match_list, char to_match)
returns true if "to_match" is found in the "match_list" string.
void pack(byte_array &target) const
stores this string in the "target". it can later be unpacked again.
bool replace(const astring &tag, const astring &replacement)
replaces the first occurrence of "tag" text with the "replacement".
int packed_size() const
Reports the size required to pack this string into a byte array.
int ifind_any(const char *to_find, int position=0, bool reverse=false) const
searches case-insensitively for any of the characters in "to_find".
void trim(int length)
shortens the string to "length" if it's longer than that.
byte_array & get_implementation()
virtual base_string & assign(const base_string &s)
Sets the contents of this string to "s".
virtual char get(int index) const
a constant peek at the string's internals at the specified index.
astring operator+(const astring &s) const
Returns the concatenation of "this" and "s".
int convert(int default_value) const
Converts the string into a corresponding integer.
astring & operator+=(const astring &s)
Modifies "this" by concatenating "s" onto it.
void copy(char *to_stuff, int count) const
Copies a maximum of "count" characters from this into "to_stuff".
virtual void zap(int start, int end)
Deletes the characters between "start" and "end" inclusively.
astring()
constructs an empty string.
bool substring(astring &target, int start, int end) const
a version that stores the substring in an existing "target" string.
void strip(const astring &strip_list, how_to_strip way=FROM_BOTH_SIDES)
strips all chars from "strip_list" out of "this" given the "way".
static const astring & empty_string()
useful wherever empty strings are needed, e.g., function defaults.
astring & base_sprintf(const char *s, va_list &args)
void shrink()
changes all occurrences of "to_replace" into "new_string".
astring & sprintf(const char *s,...)
similar to the SPRINTF constructor, but works on an existing string.
virtual base_string & concatenate_string(const base_string &s)
Modifies "this" by concatenating "s" onto it.
void to_upper()
to_upper does the opposite of to_lower (that is, q becomes Q).
virtual void text_form(base_string &state_fill) const
Provides a text view of all the important info owned by this object.
bool iequals(const astring &that) const
returns true if this is case-insensitively equal to "that".
astring left(int count)
returns the left "count" characters from the string.
void insert(int position, const astring &to_insert)
Copies "to_insert" into "this" at the "position".
void pad(int length, char padding=' ')
makes the string "length" characters long.
virtual base_string & concatenate_char(char c)
concatenater for single characters.
void reset()
clears out the contents string.
int find_non_match(const char *to_find, int position=0, bool reverse=false) const
searches for any character that is not in "to_find" and returns index.
bool equal_to(const char *that) const
returns true if "that" is equal to this.
int end() const
returns the index of the last (non-null) character in the string.
virtual bool less_than(const orderable &s2) const
virtual int comparator(const astring &s2) const
helps to fulfill orderable contract.
char & operator[](int position)
accesses individual characters in "this" string.
int find_any(const char *to_find, int position=0, bool reverse=false) const
searches for any of the characters in "to_find".
astring right(int count)
returns the right "count" characters from the string.
virtual void put(int position, char to_put)
stores the character "to_put" at index "position" in the string.
bool replace_all(char to_replace, char new_char)
changes all occurrences of "to_replace" with "new_char".
int length() const
Returns the current length of the string.
bool unpack(byte_array &source)
retrieves a string (packed with pack()) from "source" into this string.
virtual char * access()
provides access to the actual string held.
astring upper() const
like to_upper(), but returns a new string rather than modifying this.
bool compare(const astring &to_compare, int start_first, int start_second, int count, bool case_sensitive) const
Compares "this" string with "to_compare".
virtual bool sub_string(base_string &target, int start, int end) const
Gets the segment of "this" between the indices "start" and "end".
int find(char to_find, int position=0, bool reverse=false) const
Locates "to_find" in "this".
bool contains(const astring &to_find) const
Returns true if "to_find" is contained in this string or false if not.
virtual bool sub_compare(const base_string &to_compare, int start_first, int start_second, int count, bool case_sensitive) const
Compares "this" string with "to_compare".
int ifind(char to_find, int position=0, bool reverse=false) const
like the find() methods above, but case-insensitive.
virtual const char * observe() const
observes the underlying pointer to the zero-terminated string.
void to_lower()
to_lower modifies "this" by replacing capitals with lower-case.
virtual base_string & upgrade(const char *s)
Sets the contents of this string to "s".
Defines the base class for all string processing objects in hoople.
virtual const char * observe() const =0
observes the underlying pointer to the zero-terminated string.
virtual base_string & assign(const base_string &s)=0
Sets the contents of this string to "s".
A very common template for a dynamic array of bytes.
Base class for object that can tell itself apart from other instances.
A base for objects that can be alphabetically (lexicographically) ordered.
Constants and objects used throughout HOOPLE.
#define NULL_POINTER
The value representing a pointer to nothing.
#define bounds_return(value, low, high, to_return)
Verifies that "value" is between "low" and "high", inclusive.
The guards collection helps in testing preconditions and reporting errors.
char simple_lower(char input)
const int MAX_FIELD_FUDGE_FACTOR
const int LONGEST_SPRINTF
const abyte empty_char_star[]
unsigned char abyte
A fairly important unit which is seldom defined...
void attach(byte_array &packed_form, const char *to_attach)
Packs a character string "to_attach" into "packed_form".
bool matches_any(char to_check, const astring &list)
target_type * cast_or_throw(source_type &to_cast, const target_type &ignored)
dynamically converts a type to a target type, or throws an exception if it cannot.
bool detach(byte_array &packed_form, astring &to_detach)
Unpacks a character string "to_attach" from "packed_form".
bool matches_none(char to_check, const astring &list)
bool imatches_any(char to_check, const astring &list)
const char CASE_DIFFERENCE
type minimum(type a, type b)
maximum returns the greater of two values.
bool negative(const type &a)
negative returns true if "a" is less than zero.
bool astring_comparator(const astring &a, const astring &b)
implements a string comparator that just does simple astring ==.
int calculate_proper_length(int repeat)